我正在尝试将一个对象用作python字典中的一个键,但它的表现方式我无法理解。
首先,我创建一个以对象为关键字的字典:
package_disseminators = {
ContentType("application", "zip", "http://other/property") : "one",
ContentType("application", "zip") : "two"
}
现在创建另一个与关键对象“相同”的对象。
content_type = ContentType("application", "zip", "http://other/property")
我已经为ContentType对象提供了自定义__eq__
和自定义__str__
方法,因此__eq__
方法会比较__str__
值。
现在,一些交互式python:
>>> for key in package_disseminators:
... if key == content_type:
... print "match"
... else:
... print "no match"
...
no match
match
>>> content_type in package_disseminators.keys()
True
好的,所以看起来我的对象肯定被正确识别为一个键,所以:
>>> package_disseminators[content_type]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: (& (type="application/zip") (packaging="http://other/property") )
呃......好吗?所以content_type在package_disseminators.keys()列表中,但不是密钥?
>>> package_disseminators.has_key(content_type)
False
显然不是。
我认为Python用于确定相等性的比较过程在列表上的直接“in”语句和实际查找dict中的键之间有所不同,但我不知道如何。任何提示或见解?
答案 0 :(得分:25)
来自python文档:
字典的键几乎是 任意值。不是的值 hashable,即包含的值 列表,词典或其他可变的 类型(按值比较 而不是通过对象身份)可能 不能用作钥匙。
Hashable定义如下
如果对象具有哈希值,则该对象是可清除的 在其期间永远不会改变的价值 一生(需要一个
__hash__()
方法),并可以与其他人进行比较 对象(它需要__eq__()
或__cmp__()
方法)。比较相等的可清洗对象必须具有相同的对象 哈希值。可持续性使对象可用作 字典键和集合成员, 因为这些数据结构使用了 内部哈希值。
因此,如果你想这样做,你需要覆盖对象的默认__hash__()
方法(请参阅下面的Steven Rumbalski的评论以获得进一步的解释)。
>>> content_type in package_disseminators.keys()
True
我认为这是有效的,因为dict.keys()
返回一个列表,__contains__
可能会检查相等性,但不会检查相同的哈希值。
答案 1 :(得分:18)
由于dicts是底层的哈希表,因此您需要同时定义__eq__
和__hash__
才能使用。
基本的经验法则是:
__eq__
比较相等的对象,__hash__
必须返回相同的哈希值。根据您的描述,例如
def __hash__(self):
return hash(str(self))
应该有用。