我有个奇怪的情况。我有一句话,self.containing_dict
。使用debug探针,我可以看到dict的内容,self
是其中的一个键。但是看看这个:
>>> self in self.containing_dict
False
>>> self in self.containing_dict.keys()
True
>>> self.containing_dict.has_key(self)
False
怎么回事?在
(我会注意到这是在weakref回调上执行的一段代码中。)
更新:我被要求展示__hash__
的self
实现。这里是:
您描述的问题只能由}而引起。如果您没有实现}的对象作为dict键,但是如果您继承了一个可能会错过的
self
实现了__eq__
(或__cmp__
)而没有实现相应的{__hash__
方法,通常情况下您不能使用定义__eq__
但不能{__hash__
。在如果您确实实现了
__hash__
,那么必须确保它的行为是正确的:在对象的生存期内(或者至少只要对象作为dict键或set项使用),结果必须与__eq__
一致。一个对象的散列值必须与它所等于的对象相同(根据它的__eq__
或__cmp__
)。一个对象的散列值可能与它不相等的对象不同,但不一定非得如此。这些要求还意味着在对象的生存期内,__eq__
的结果不能更改,这就是为什么可变对象通常不能用作dict键。在如果您的}中,这就是您在这里描述的。实现
__hash__
和__eq__
不匹配,Python将无法在dicts和set中找到该对象,但它仍然会出现在dict.keys()
和{__hash__
方法的通常方法是返回__eq__
或__cmp__
方法中使用的任何属性的hash()
。在很可能您已经为任何类
self
定义了自定义哈希和比较,并且您在将self
添加到字典后对其进行了变异。在如果使用可变对象作为字典键,那么在对其进行变异之后,您可能无法在字典中访问它,但它仍将出现在
keys()
结果中。在从您的
__hash__
方法判断,该类存储对其参数的引用,并将其用作哈希。问题是,这些参数与构造对象的代码共享。如果他们改变了参数,散列也会改变,你将无法在它所在的任何字典中找到这个对象。在论点不必复杂,只要一个简单的列表就可以了。在
如果我更改作为参数传递的列表,哈希值将更改。在
^{pr2}$因为字典键是按散列组织的,所以当我使用
x in d
时,Python做的第一件事就是计算x的散列值,并在字典中查找具有该散列值的内容。问题是,当一个对象的哈希值在放入字典后发生变化时,Python会查看新的哈希值,而不会在那里看到所需的键。使用键列表,强制Python通过相等方式检查每个键,从而绕过哈希检查。在相关问题 更多 >
编程相关推荐