Python - 包装相同的对象以使其唯一

时间:2016-12-12 09:35:17

标签: python python-2.7 object unique instance

我有一个在迭代对象时正在构建的字典。现在可以多次访问同一个对象。而且我使用对象本身作为关键。

因此,如果同一个对象被多次访问,那么密钥就不会是唯一的,而且我的字典不再正确。

虽然我需要通过对象访问它,因为如果有人想要通过它访问内容,他们可以请求通过当前对象获取它。它是正确的,因为它将在那时访问最后一个活动对象。

所以我想知道是否有可能以某种方式包装对象,所以它会保持其状态和所有属性相同,但唯一的区别是这种新的对象实际上是唯一的。

例如:

dct = {}

for obj in some_objects_lst:
    # Well this kind of wraps it, but it loses state, so if I would
    # instantiate I would lose all information that was in that obj.
    wrapped = type('Wrapped', (type(obj),), {})
    dct[wrapped] = # add some content

现在,如果有更好的替代方案,我也想听听。

P.S。被迭代的对象将处于不同的上下文中,因此即使对象是相同的,它也会被区别对待。

更新

根据要求,提供问题来自的更好示例:

我有这个excel报告生成器模块。使用它,您可以生成各种Excel报告。为此,您需要使用python词典编写配置。

现在,在生成报告之前,它必须做两件事。获取元数据(这里的元数据是将要创建报告时每个单元格的位置),其次是解析配置以填充包含内容的单元格。

此模块中可以使用的值类型之一是公式(excel公式)。我的问题中的问题特别是可以计算公式的方法之一:为父项检索的公式值,即在其子项中。

例如想象一下这个excel文件结构:

  A          | B          | C
  Total        Childs Name Amount
1 sum(childs)
2              child_1      10
3              child_2      20

4 sum(childs)
  ...

现在在这个例子中,单元格1A的总和,如果sum将使用表达式对其子列进行求和(在本例中为C列),则需要为10 + 20 = 30。所有这一切都在工作,直到重复相同的对象(我称之为迭代)。因为在构建元数据时我需要存储它,以便以后检索。关键是对象本身是迭代的。所以现在当它在解析值时再次迭代时,它将不会看到所有信息,因为有些信息会被同一个对象覆盖。

例如,想象有发票对象,然后有与发票相关的合作伙伴对象,还有一些其他任意对象给出发票和合作伙伴产生特定金额。

因此,当在excel中提取此类信息时,它是这样的:

inoice1 -> partner1 -> amount_obj1, amount_obj2
invoice2 -> partner1 -> amount_obj3, amount_obj4.

请注意,示例中的合作伙伴是相同的。这是问题,因为我无法将其存储为密钥,因为在解析值时,当元数据实际保存amount_obj3amount_obj4

P.S不知道我是否更好地解释了它,因为有很多代码而且我不想在这里放置大量的代码。

UPDATE2

我试图从更抽象的角度解释这个问题,因为它似乎过于具体,只会让每个人更加困惑。

因此,给定对象列表和空字典,通过迭代对象来构建字典。对象充当字典中的键。它包含稍后使用的元数据。

现在可以为了不同的目的再次迭代相同的列表。完成后,它需要使用迭代对象(相同的对象,即该字典中的键)访问该字典值。但问题是,如果同一个对象被多次使用,它将只有该键的最新存储值。

这意味着对象不是唯一键。但问题是我唯一知道的是对象(当我需要检索值时)。但是因为它是相同的迭代,所以当两次访问同一个对象时,特定的迭代索引将是相同的。

因此,我认为唯一性是(index, object)

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解你的问题,所以这里有两个选择。如果它的对象内容很重要,请将对象副本保存为密钥。像

那样粗糙的东西
new_obj = copy.deepcopy(obj)
dct[new_obj] = whatever_you_need_to_store(new_obj)

如果对象在第一次被您的代码和下一个代码检查之间没有变化,则该操作仅在第二次执行时无效。不是最佳的,但可能不是一个大问题。但是,如果确实发生了变化,您将获得新旧记录的单独记录。为了节省内存,您可能希望用散列替换副本,__str__()方法写入对象数据或其他任何内容。但这取决于你的对象是什么;也许哈希会花费太多时间来节省大量内存。运行一些测试,看看哪些有效。

另一方面,如果为同一个对象保持相同的值很重要,那么它内部的数据是否已经改变(比如,对象是一个可以在登录之间更改其数据的用户会话)和注销),使用对象ID。不是内置id()函数,因为如果对象被GCed或删除,其他一些对象可能会得到它的id。为对象定义id属性,并确保不同的对象不可能获得相同的对象。