【问题标题】:How can I make my classes usable as dict keys?如何使我的类可用作 dict 键?
【发布时间】:2011-07-10 10:11:51
【问题描述】:
class A():
   def __init__(self, data=''):
       self.data = data  

   def __str__(self):
       return str(self.data)

d = {}  
elem = A()  
d[elem] = 'abc'  

elem2 = A()
print d[elem2]    # KeyError  
# actually elem2! was used not elem

如何才能不出错?

我试图用另一个 A() 实例获取 d[elem2](不是 elem),但内容相同。

【问题讨论】:

  • 什么错误(消息)?它真的只发生在你访问一个元素时,而不是设置它?您真的(如示例中)在两行中使用相同的实例,还是等于d[A()] = ...; print d[A()]
  • 是的,只在获取时,不设置。编辑:KeyError。
  • @Sergey:你将不得不告诉我们更多关于A的课程。您是否覆盖了任何特殊方法?发布错误消息时,请提供完整的错误消息,包括回溯。
  • 定义了 initstr 就像我上面写的那样
  • 更新后的代码对我来说运行没有错误。

标签: python dictionary key


【解决方案1】:

只要您不覆盖 __hash__()__eq__() 方法,您所做的应该可以工作。它将使用对象身份作为相等性。如果您想要不同的相等概念,您可以覆盖您的类的 __hash__()__eq__() 方法。

【讨论】:

  • hasheq 的小例子会很棒
  • 什么定义了对象的身份?也就是说,如果您更改它们,哪些字段会导致对象代表另一个实体?假设对象代表一个人并包含一个唯一标识符,如 SSN。然后您可能会决定,如果两个对象的ssn 属性相同,那么即使它们的名称不同,它们也是相等的(因为人们可以更改它们的名称)。然后,您将编写 __eq__() 以仅比较 self.ssn__hash__() 以返回 hash(self.ssn)。可以考虑任意数量的字段,具体取决于对象所代表的内容。
【解决方案2】:

答案是肯定的,你需要重新定义__hash__()__eq__()

>>> class A(object):
...   def __init__(self, data=''):
...     self.data = data
...   def __eq__(self, another):
...     return hasattr(another, 'data') and self.data == another.data
...   def __hash__(self):
...     return hash(self.data)
... 
>>> a1, a2, a3 = A('foo'), A('foo'), A('bar')
>>> d = {a1: 'foo'}
>>> d[a1]
'foo'
>>> d[a2]
'foo'
>>> d[a3]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: __main__.A object at 0x927d0>

正如另一条评论中所解释的,__hash__ 的默认实现只是简单的标识,所以如果你想让它更复杂,你需要明确地定义它。

【讨论】:

  • 你还需要实现__eq__,否则会发生奇怪的事情(至少在Python 2.7中),我已经为你测试过了……
猜你喜欢
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多