Python - 关于哈希和`None`的问题

4 投票
4 回答
909 浏览
提问于 2025-04-16 14:30

为什么 None 的哈希值是 -1042159082(我发现这个值等于一个千兆字节的字节数的负值)呢?

我知道这对我的代码没有影响,但我很好奇。

哈希值通常用来在字典中查找键,所以我决定做个实验:

>>> D = {-1042159082: 'Hello', None: 'Hi'}
>>> D[None]
'Hi'
>>> D[-1042159082]
'Hello'
>>>

我理解为 Python 看到两个相同的哈希值,然后再检查类型来区分它们。这样理解对吗?

>>> {False: 'Hello', 0: 'Hi'}
{False: 'Hi'}
>>> {0: 'Hi', False: 'Hello'}
{0: 'Hello'}

这真让人费解。更奇怪的是,第一个键被保留,而第二个值也被保留。

这是魔法吗,还是有人能帮我理解一下?

4 个回答

2

不,即使两个对象的哈希值恰好相同,它们也不会导致键冲突。Python会检测到这一点并进行处理(不过请不要问我具体是怎么做到的)。

不过,False0 是一样的,True1 也是一样的,所以当你在构建字典时同时使用这两个值时,如果你再添加一个相同键的项,就会更新这个键的值。

4

你不能也不应该依赖于某个特定的哈希值来判断一个Python对象。这是因为哈希值的生成和机器的具体实现有关。在我的机器上:

>>> hash(None)
268532216

关于如何填充dict对象(Python里没有hash对象),也许下面的内容会对你有帮助:

>>> False == 0
True
>>> {0: 'Hello', 0: 'Hi'}
{0: 'Hi'}
>>> {0: 'Hi', 0: 'Hello'}
{0: 'Hello'}
>>> {False: 'Hello', False: 'Hi'}
{False: 'Hi'}
>>> {False: 'Hi', False: 'Hello'}
{False: 'Hello'}

当你使用dict构造函数时,你提供了两个key=value对,但这两个对的键是相同的(也就是说,它们是可哈希的值)。由于字典中的键值必须是唯一的,所以最后一个值会被保存。换句话说,上面的每个构造函数实际上都在创建一个只有一个元素的字典:

>>> print {False: 'Hello', 0: 'Hi'}
{False: 'Hi'}

想了解更多信息,可以查看这里

5

关于两个可能在传给内置的 hash() 函数时产生相同输出的值(在提问中提到的 None-1042159082):

这种情况叫做碰撞(想了解更多关于碰撞的信息,可以查看维基百科的这篇文章)。

Python使用的哈希算法有一种特别的方法来判断在发生碰撞时,用户真正想要的是哪个值(想了解字典碰撞的相关信息,可以查看CPython源代码中的这篇文章,从第51行开始;这个文件也有关于字典实现的说明)。

关于 0False 的情况(以及更多有用的信息),可以查看其他人对当前问题的回答。

撰写回答