为什么在字典中为键 `True` 赋值会覆盖同一字典中键 `1` 的值?

3

对于这个简单的字典 -

键1和值“apple”总是打印为“1:False”。

我是否忽略了一些原因?

$ cat dict.py

pairs = {1: "apple",
    "orange": [2, 3, 4], 
    True: False, 
    None: "True",
}
print(pairs)

*$ python3.8 dict.py

{1: False, 'orange': [2, 3, 4], None: 'True'}

谢谢


2
True/False是整数1/0的特殊情况,但它们属于不同的类别(布尔类)。这对我来说似乎是一个错误 - 直觉上,我不希望用True:False覆盖我的整数1键。在3.7中也是如此。 - Patrick Artner
1
对于 p = {},p [1] =“apple”,p [True] = False,print(p) 相同的操作会用 False 覆盖 apple - Patrick Artner
2
hash(1) == hash(True) 但我同意这种行为并不直观。 - snakecharmerb
1
在Python v2.7.13中也是如此-看起来似乎是一件被接受的事情。还有一个需要记住的奇怪之处-但我可能永远不会在字典中使用True和ints作为键... - Patrick Artner
非常感谢!我一直在练习,想要理解一切的工作原理和原因,我相信你也能理解 --- 我会记下这个! - Jake Cope
1个回答

5
在Python中,bool类型是int的子类型,其中True等于数字1,而False等于数字0
>>> True == 1
True
>>> False == 0
True

当这些值被散列时,它们也会分别产生相同的值:
>>> hash(True)
1
>>> hash(1)
1
>>> hash(False)
0
>>> hash(0)
0

现在,由于字典键是基于哈希和对象相等性的(首先使用哈希相等性快速查找可能相等的键,然后通过相等性比较它们),导致两个值产生相同的哈希并且相等将会在字典的相同“位置”中。

如果您创建具有此行为的自定义类型,也可以看到这一点:

>>> class CustomTrue:
        def __hash__(self):
            return 1
        def __eq__(self, other):
            return other == 1

>>> pairs = {
        1: "apple",
        "orange": [2, 3, 4], 
        True: False, 
        None: "True",
    }
>>> pairs[CustomTrue()] = 'CustomTrue overwrites the value'
>>> pairs
{1: 'CustomTrue overwrites the value', 'orange': [2, 3, 4], None: 'True'}

虽然这解释了这种行为,但我同意它可能有点令人困惑。因此,我建议不要使用不同类型的字典键,这样就不会遇到这种情况。


这是一个真正深入的回答,我会继续研究它- 我为你鼓掌并表示感谢。 - Jake Cope
@JakeCope 很高兴我能帮到你!如果这个回答解决了你的问题,请考虑接受答案来标记问题已解决。 - poke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接