Python - 关于哈希和“无”的问题

时间:2011-03-27 06:08:18

标签: python

为什么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 个答案:

答案 0 :(得分:6)

传递给内置hash()函数(问题中None-1042159082)时,可能产生相同输出的大约2个值:

这称为碰撞(有关碰撞的更多信息,请参阅维基百科上的this页面。)

Python使用的散列算法有一种特殊的方法可以确定出现碰撞时该人真正想要的值(请参阅CPython源代码中的this页面(主要的Python解释器),从第51行,关于dicts冲突的信息,在撰写本答案时; this文件还记录了如何实现dicts。

关于0False会发生什么(以及更多有用的信息),请参阅当前问题的其他答案。

答案 1 :(得分:3)

您不能也不应该依赖于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对,但它们都具有相同的键(即可散列值),因此,因为dict中的键值必须是唯一的,所以value是保存的值。换句话说,上面的每个构造函数都创建了一个单项dict:

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

有关详细信息,请参阅here

答案 2 :(得分:2)

不,即使两个对象恰好具有相同的哈希值,它们仍然不会导致密钥冲突。 Python检测到它并解决它(虽然请不要问我怎么做)。

但是False0相同而True1相同,所以当你在dict构造中同时使用它们时,你就会更新添加具有相同键的其他项时的值。

答案 3 :(得分:0)

你如何计算没有哈希值?

>>> d = {None:'hi'}
>>> d.get(-1042159082)
>>> d.get(None)
'hi'
>>>
>>> hash(None)
268532214
>>>

我不会依赖哈希值的值。

至于使用文字的字典分辨率,我假设在内部,定义一个'等于'另一个的键,只会进行更新而不是直接添加。

>>> class Key(object):
...     key = '1'
...     def __hash__(self):
...         return 1
...     def __eq__(self, other):
...         return hash(self) == hash(other)
... 
>>> class FakeKey(Key):
...     key = '2'
... 
>>> k = Key()
>>> >>> fk = FakeKey()
>>> d = {k:k,fk:fk}
>>> d
{<__main__.Key object at 0x100489f10>: <__main__.FakeKey object at 0x100489fd0>}
>>> ref = d[k]
>>> ref.key
'2'
>>> d.keys()[0].key
'1'
>>> 

出现我是对的(仅出现)。