【问题标题】:What's the order of __hash__ and __eq__ evaluation for a Python dict?Python dict 的 __hash__ 和 __eq__ 评估的顺序是什么?
【发布时间】:2016-11-01 11:43:11
【问题描述】:

我试图了解 Python 字典必须在内部做什么才能找到键。在我看来,hash 将首先被评估,如果发生冲突,Python 将遍历键,直到找到 eq 返回 True 的键。这让我想知道为什么以下代码有效(测试代码仅用于理解内部):

class MyClass(object):
    def __eq__(self, other):
        return False

    def __hash__(self):
        return 42

if __name__=='__main__':

    o1 = MyClass()
    o2 = MyClass()
    d = {o1: 'o1', o2: 'o2'}
    assert(o1 in d)      # 1
    assert(d[o1]=='o1')  # 2
    assert(o2 in d)      # 3
    assert(d[o2]=='o2')  # 4

字典是否应该找不到正确的键(在 #2 和 #4 两种情况下都返回“o1”或“o2”,或者抛出错误,具体取决于内部实现)。在这两种情况下,当它永远不能正确“等同”键(因为 eq 返回 False)时,它如何能够在正确的键上着陆。

我看到的所有关于散列的文档总是一起提到 hasheq,从来没有提到 cmpne 等等,这让我认为这两个是唯一在这种情况下发挥作用的。

【问题讨论】:

    标签: python dictionary hashable


    【解决方案1】:

    您用作字典键的任何内容都必须满足bool(x == x) is True 的不变量。 (我会说x == x,但有一些合理的对象甚至不是布尔值。)

    dict 假设这将成立,因此它用于检查密钥相等性的例程实际上在使用== 之前首先检查对象身份。这个初步检查是一个实现细节;你不应该依赖它发生或不发生。

    (x == x) is not True 的合理对象包括float('nan')numpy.array([1, 2])

    【讨论】:

    • 所以在他的例子中 o1 == o1 会返回 False,但 id(o1) == id(o1) 会返回 True?
    • 我刚试了一下,o1 == o1 返回 False,id(o1) == id(o1) 返回 True
    • @TimurRidjanovic:是的。不过,is 是比较对象身份的一种更安全、有时更有效的方法。
    猜你喜欢
    • 2010-09-18
    • 2011-03-05
    • 2015-11-02
    • 2023-03-03
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多