1

我有一堆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, ...))

这当然行不通,因为当对象的内容改变时,它的哈希值(因此它的身份)改变了,一切都变得一团糟。我需要的是一个保持其身份的对象,尽管它的内容发生了变化。我尝试了各种方法,例如 make __hash__return id(self)、 overriding__eq__等,但从未找到令人满意的解决方案。一个复杂的问题是整个结构应该是可腌制的,所以这意味着我必须id在创建时存储,因为它可能会在腌制时发生变化,我猜。

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

4

2 回答 2

0

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

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

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

另请参阅:我可以在 python 中使用可变对象作为字典键。这不是不允许的吗?

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

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

于 2013-07-26T16:33:47.100 回答
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]
于 2013-07-26T13:58:11.550 回答