【问题标题】:Python: Accessing dict with hashable object failsPython:使用可散列对象访问 dict 失败
【发布时间】:2022-01-25 13:33:01
【问题描述】:
我使用可散列对象作为字典的键。这些对象是可散列的,我可以将键值对存储在 dict 中,但是当我创建同一对象的副本(给我相同的散列)时,我得到一个 KeyError。
这是一些小示例代码:
class Object:
def __init__(self, x): self.x = x
def __hash__(self): return hash(self.x)
o1 = Object(1.)
o2 = Object(1.)
hash(o1) == hash(o2) # This is True
data = {}
data[o1] = 2.
data[o2] # Desired: This should output 2.
在我上面的场景中,我怎样才能实现data[o2] 也返回2.?
【问题讨论】:
标签:
python
python-3.x
dictionary
【解决方案1】:
你需要同时实现__hash__和__eq__:
class Object:
def __init__(self, x): self.x = x
def __hash__(self): return hash(self.x)
def __eq__(self, other): return self.x == other.x if isinstance(other, self.__class__) else NotImplemented
每Python documentation:
如果一个类没有定义__eq__() 方法,它也不应该定义__hash__() 操作
找到散列后,Python 的字典使用 __eq__ 比较键并意识到它们是不同的,这就是你没有得到正确输出的原因。
【解决方案2】:
您可以使用__eq__ 魔术方法对您的对象实施相等检查。
def __eq__(self, other):
if (isinstance(other, C)):
return self.x == self.x
您可以通过link了解更多关于魔法方法的信息。
【解决方案3】:
所以如前所述,你的对象需要实现 __ eq__ trait(平等 ==),如果你想了解原因:
有时不同对象的哈希值相同,这称为冲突。
字典通过测试对象是否相等来管理它。如果它们不是字典,则必须管理冲突。他们如何做到这一点是实施细节,并且可能会有很大差异。一个虚拟实现将是元组键值列表。
在后台,一个虚拟实现可能看起来像这样:
dico[key] = [(object1, value), (object2, value)]