__hash__ 和 __eq__ 对 Python 字典的求值顺序是什么?
What's the order of __hash__ and __eq__ evaluation for a Python dict?
我正在尝试了解 Python 词典必须在内部执行哪些操作才能找到键。在我看来 hash 将首先被评估,如果发生冲突,Python 将遍历键直到找到一个 eq returns 没错。这让我想知道为什么以下代码有效(测试代码仅用于了解内部结构):
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',或者抛出错误,具体取决于内部实现) .在这两种情况下,当它永远无法正确 'equate' 键时(因为 eq returns False),它如何能够找到正确的键。
我看到的所有关于散列的文档总是同时提到 hash 和 eq,从来没有提到 cmp、ne 等,这让我觉得这两个是唯一在这种情况下发挥作用的。
任何用作字典键的东西都必须满足 bool(x == x) is True
的不变量。 (我会说 x == x
,但有些合理的对象甚至不是布尔值。)
dict 假定这将成立,因此它用于检查键相等性的例程实际上在使用 ==
之前先检查对象标识。这个初步检查是一个实现细节;你不应该依赖它发生或不发生。
(x == x) is not True
的合理对象包括float('nan')
和numpy.array([1, 2])
。
我正在尝试了解 Python 词典必须在内部执行哪些操作才能找到键。在我看来 hash 将首先被评估,如果发生冲突,Python 将遍历键直到找到一个 eq returns 没错。这让我想知道为什么以下代码有效(测试代码仅用于了解内部结构):
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',或者抛出错误,具体取决于内部实现) .在这两种情况下,当它永远无法正确 'equate' 键时(因为 eq returns False),它如何能够找到正确的键。
我看到的所有关于散列的文档总是同时提到 hash 和 eq,从来没有提到 cmp、ne 等,这让我觉得这两个是唯一在这种情况下发挥作用的。
任何用作字典键的东西都必须满足 bool(x == x) is True
的不变量。 (我会说 x == x
,但有些合理的对象甚至不是布尔值。)
dict 假定这将成立,因此它用于检查键相等性的例程实际上在使用 ==
之前先检查对象标识。这个初步检查是一个实现细节;你不应该依赖它发生或不发生。
(x == x) is not True
的合理对象包括float('nan')
和numpy.array([1, 2])
。