对象作为python词典中的键

Ric*_*d J 16 python dictionary

我试图将一个对象用作python字典中的一个键,但它的表现方式我无法理解.

首先,我创建一个以对象为关键字的字典:

package_disseminators = {
  ContentType("application", "zip", "http://other/property") : "one",
  ContentType("application", "zip") : "two"
}
Run Code Online (Sandbox Code Playgroud)

现在创建另一个与关键对象"相同"的对象.

content_type = ContentType("application", "zip", "http://other/property")
Run Code Online (Sandbox Code Playgroud)

我已经为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
Run Code Online (Sandbox Code Playgroud)

好的,所以看起来我的对象肯定被正确识别为一个键,所以:

>>> package_disseminators[content_type]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: (& (type="application/zip") (packaging="http://other/property") )
Run Code Online (Sandbox Code Playgroud)

呃......好吗?所以content_type在package_disseminators.keys()列表中,但不是密钥?

>>> package_disseminators.has_key(content_type)
False
Run Code Online (Sandbox Code Playgroud)

显然不是.

我假设Python用来确定相等性的比较过程在列表上的直接"in"语句和实际查找dict中的键之间有所不同,但我不知道如何.任何提示或见解?

Rei*_*cke 26

从python文档:

字典的键几乎是任意值.不可清除的值,即包含列表,字典或其他可变类型(通过值而不是按对象标识进行比较)的值不能用作键.

Hashable定义如下

一个目的是可哈希如果它有一个哈希值其寿命(它需要一个在这期间从不改变__hash__() 方法),并且可相对于其他对象(它需要一个__eq__()__cmp__()方法).比较相等的可哈希对象必须具有相同的哈希值.

Hashability使对象可用作字典键和set成员,因为这些数据结构在内部使用哈希值.

因此,如果您想这样做,您需要覆盖__hash__()对象的默认方法(请参阅下面的Steven Rumbalski的评论以获得进一步的解释).


>>> content_type in package_disseminators.keys()
True
Run Code Online (Sandbox Code Playgroud)

我认为这是有效的,因为dict.keys()返回一个列表,__contains__可能会检查相等性,但不会检查相同的哈希值.

  • 进一步澄清:您的对象已经有一个从`object`继承的`__hash__`方法.但是默认实现为每个实例返回一个唯一值,因此除非您提供更好的实现,否则两个相等的实例将具有不同的哈希值.`has_key`比较哈希值,`in`检查是否相等,这就是为什么`has_key`失败而`in`在你的例子中成功的原因. (8认同)

nos*_*klo 20

由于dicts是引擎盖下的哈希表,因此您需要定义两者__eq____hash__为此工作.

基本的经验法则是:

  • 对于__eq__比较相等的对象,__hash__必须返回相同的哈希.

从你的描述,像

def __hash__(self):
    return hash(str(self))
Run Code Online (Sandbox Code Playgroud)

应该管用.

  • 感谢`__hash__`的实现!不幸的是,我无法为一个问题分配两个正确的答案,尽管你和其他人的组合是我需要的一切.干杯,R. (3认同)