gpt4 book ai didi

Python:如果键不在字典中,为什么不调用 __eq__()?

转载 作者:行者123 更新时间:2023-11-28 22:16:40 26 4
gpt4 key购买 nike

目前,我正在研究 Python 的内置类型。我很困惑调用什么方法来检查键是否在字典中。例如,如果我检查 int 类型的键是否在字典中,则仅当 dictionary.keys() 包含它时,才会在后台调用 __eq__() 方法.如果不是,则不调用 __eq__()

这是一个代码示例:

dict = {
1: "Hello",
2: "World",
4: "Foo"
}

assert 1 in dict.keys() # the __eq__() method of int is invoked
assert not(3 in dict.keys()) # no __eq__() method of int is invoked

我知道,字典包含哈希(键)、键和值的元组。但是我有点困惑,为什么 __eq__() 没有在第二个断言中被调用。

为了测试这个行为,我从 int 继承并设置了一些断点。这是我的自定义 int 类的摘录:

tint(int):
def __new__(cls, value, *args, **kw):
return super(tint, cls).__new__(cls, value)

def __init__(self, value):
super().__init__()

def __eq__(self, other):
return super().__eq__(other) # with breakpoints

def __ne__(self, other):
return super().__ne__(other) # with breakpoints

def __hash__(self):
return tint(super().__hash__()) # with breakpoints

我在 Ubuntu 18.04.1 LTS 上使用 Python 3.6.5 版。

最佳答案

要在字典中找到一个键,您首先要通过哈希找到候选者,然后看看它是侥幸(尽管哈希相同,但对象不同)还是您真正想要的键。因此,如果您在该散列下找不到任何内容,则没有什么可 eq 的。

想象一下,您正在聚会上寻找熟人,但不知道她是否在场。她有红色的头发。通常,你会寻找红发女孩,然后去面对她们,看看是不是真的是她。如果还没有红发女孩来,检查聚会上的每一个人是没有意义的。 (假设您的 friend 不喜欢日常染色工作。)

编辑:CPython 将字典存储在一个数组中,其中主数组位置由散列确定;如果那个位置被占用,它会以数学上确定的方式跳到下一个候选位置。由于填充的位置因此可以保存“正确的”散列或不相关的散列,当查找散列时,CPython 将从主要位置开始,然后继续比较散列,直到它确定所搜索的 key 不可能存在。此时哈希是普通的低级整数,而不是 Python 对象,这解释了为什么哈希比较不会触发 __eq__

请注意源代码中的一个可爱的优化:对于每个候选对象,CPython 首先检查对象身份;只有这样它才会检查哈希值是否仍然相同,如果是,则进行慢速检查以查看对象是否相等(使用 PyObject_RichCompareBool,最终调用 __eq__)。为什么这很重要?看这里:

class Foo:
def __eq__(self, other):
return False # This shouldn't match...
def __hash__(self):
return 7

f = Foo()
d = { f: "Yes!" }
print(d[f]) # ...and yet it does! :)
# => "Yes!"

关于Python:如果键不在字典中,为什么不调用 __eq__()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52037437/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com