Python - 关于哈希和`None`的问题
为什么 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 个回答
不,即使两个对象的哈希值恰好相同,它们也不会导致键冲突。Python会检测到这一点并进行处理(不过请不要问我具体是怎么做到的)。
不过,False
和 0
是一样的,True
和 1
也是一样的,所以当你在构建字典时同时使用这两个值时,如果你再添加一个相同键的项,就会更新这个键的值。
你不能也不应该依赖于某个特定的哈希值来判断一个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'}
想了解更多信息,可以查看这里。
关于两个可能在传给内置的 hash()
函数时产生相同输出的值(在提问中提到的 None
和 -1042159082
):
这种情况叫做碰撞(想了解更多关于碰撞的信息,可以查看维基百科的这篇文章)。
Python使用的哈希算法有一种特别的方法来判断在发生碰撞时,用户真正想要的是哪个值(想了解字典碰撞的相关信息,可以查看CPython源代码中的这篇文章,从第51行开始;这个文件也有关于字典实现的说明)。
关于 0
和 False
的情况(以及更多有用的信息),可以查看其他人对当前问题的回答。