使用python dict查找可变对象

时间:2013-07-26 09:10:28

标签: python dictionary

我有一堆File个对象和一堆Folder个对象。每个文件夹都有list个文件。现在,有时我想查找某个文件所在的文件夹。我不想遍历所有文件夹和文件,因此我创建了一个查找dict文件 - >文件夹中。

folder = Folder()
myfile = File()
folder_lookup = {}

# This is pseudocode, I don't actually reach into the Folder
# object, but have an appropriate method
folder.files.append(myfile)
folder_lookup[myfile] = folder

现在,问题是,文件是可变对象。我的应用程序是围绕这个事实构建的我更改了它们的属性,并相应地通知和更新GUI。当然你不能把可变对象放在dicts中。所以我首先尝试的是基于当前内容生成哈希,基本上是:

def __hash__(self):
    return hash((self.title, ...))

这当然没有用,因为当对象的内容改变了它的哈希值(因此它的身份)改变了,一切都搞砸了。我需要的是一个保持其身份的对象,尽管它的内容会发生变化。我尝试了各种各样的事情,例如让__hash__返回id(self),覆盖__eq__等等,但从未找到令人满意的解决方案。一个复杂的问题是整个结构应该是可伪装的,这意味着我必须在创建时存储id,因为它可能会在酸洗时发生变化,我想。

所以我基本上想要使用对象的身份(而不是它的状态)来快速查找与该对象相关的数据。我实际上已经为我的问题找到了一个非常好的pythonic解决方法,我可能很快会发布,但我想看看是否有其他人提出了解决方案。

2 个答案:

答案 0 :(得分:0)

我觉得写这个很脏。只需将文件夹作为属性放在文件中即可。

class dodgy(list):
    def __init__(self, title):
        self.title = title
        super(list, self).__init__()
        self.store = type("store", (object,), {"blanket" : self})
    def __hash__(self):
        return hash(self.store)

innocent_d = {}
dodge_1 = dodgy("dodge_1")
dodge_2 = dodgy("dodge_2")
innocent_d[dodge_1] = dodge_1.title
innocent_d[dodge_2] = dodge_2.title

print innocent_d[dodge_1]
dodge_1.extend(range(5))
dodge_1.title = "oh no"
print innocent_d[dodge_1]

答案 1 :(得分:0)

好的,每个人都注意到非常明显的解决方法(花了我几天的时间才想出来),只需在File上放一个属性,告诉你它在哪个文件夹中。(别担心,这是我也做了什么。)

但是,事实证明我在错误的假设下工作。你不应该使用可变对象作为键,但这并不意味着你不能(恶魔般的笑声)! __hash__的默认实现返回一个唯一值,可能是从对象的地址派生的,并且在时间上保持不变。默认的__eq__遵循相同的对象标识概念。

因此,您可以将可变对象放入dict中,并且它们按预期工作(如果您希望基于实例而不是基于值的相等)。

另请参阅:I'm able to use a mutable object as a dictionary key in python. Is this not disallowed?

我遇到了问题,因为我正在腌制/去除物体,这当然改变了哈希。可以在构造函数中生成唯一ID,并将其用于相等性并派生哈希来克服这个问题。

(好奇的是,为什么这样的“基于实例身份的查找”字典可能是必要的:我一直在试验一种"object database"。你有纯粹的python对象,把它们放在列表中/容器,并且可以在属性上定义索引以便更快地查找,复杂查询等等。对于外键(1:n关系)我可以只使用容器,但对于反向链接,我必须想出一些聪明的东西,如果我不我想修改 n 方面的对象。)