【问题标题】: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)]
      

      【讨论】:

        猜你喜欢
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 2018-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-06
        • 2012-09-25
        相关资源
        最近更新 更多