对于Python dict,__ hash__和__eq__评估的顺序是什么?

Vin*_*sal 5 python dictionary hashable

我试图理解Python字典必须在内部做什么才能找到密钥.在我看来,哈希将首先被评估,如果有冲突,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
Run Code Online (Sandbox Code Playgroud)

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

我在哈希上看到的所有文档总是提到哈希eq,而不是cmp,ne等,这让我觉得这两个是唯一在这个场景中发挥作用的人.

use*_*ica 5

你用作dict键的任何东西都必须满足不变量bool(x == x) is True.(我会说x == x,但有合理的对象,甚至不是布尔值.)

dict假定这将保持,因此它用于检查键相等性的例程实际上在使用之前首先检查对象身份==.这个初步检查是一个实施细节; 你不应该依赖它发生或不发生.

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