【发布时间】:2015-08-13 17:56:54
【问题描述】:
我了解以下内容在 Python 中有效:foo = {'a': 0, 1: 2, some_obj: 'c'}
但是,我想知道内部是如何工作的。它是否将所有内容(对象、字符串、数字等)都视为对象?它是否通过类型检查来确定如何计算给定键的哈希码?
【问题讨论】:
标签: python
我了解以下内容在 Python 中有效:foo = {'a': 0, 1: 2, some_obj: 'c'}
但是,我想知道内部是如何工作的。它是否将所有内容(对象、字符串、数字等)都视为对象?它是否通过类型检查来确定如何计算给定键的哈希码?
【问题讨论】:
标签: python
暂时忽略字典可能更容易,只考虑集合。您可能会看到一组s 可能由{'a', 1, some_object} 组成,对吧?如果您尝试将1 添加到此集合中,它不会做任何事情(因为1 已经存在)?
现在,假设您尝试将another_object 添加到s。 another_object不是1或'a',所以看是否可以添加到s,Python会看another_object是否等于some_object。理解对象相等是一个完整的nother 主题,但我只想说,有一种明智的方法可以解决它。如果another_object == some_object 为真,那么s 将保持不变。否则,s 将由 {'a', 1, some_object, another_object} 组成。
希望这对您有意义。如果是这样,那么只需将字典视为特殊集合。字典的键是集合的条目,字典的值只为每个键保存一个值。说d['and now'] = 'completely different' 与从集合中删除'and now' 相同,然后以'completely different' 作为其关联值再次添加它。 (从技术上讲,这不是 dict 处理 __setitem__ 的方式,但认为 dict 以这种方式工作可能会有所帮助。实际上,集合更像是残缺的 dicts,而不是 dicts 就像更强大的集合)。
当然,对于字典,您应该记住,字典中只允许散列对象。但这本身就是一个不同的主题,并不是你问题的症结所在,AFAICT
【讨论】:
Python 中的一切都是对象,每个具有__hash__ 方法的对象都可以用作字典键。因此,该方法(试图)如何为每个可能的键返回一个唯一的整数是特定于每个类的,并且有些私有(为了幽默效果而粗心地使用该术语)。详情请见https://wiki.python.org/moin/DictionaryKeys。
(在完全可散列之前,您的类还需要支持其他几种方法。再次,请参阅链接的说明。)
【讨论】:
您可以通过打开 Python 交互式提示并尝试以下几个键来回答这个问题:
>>> hash('a')
12416037344
>>> hash(2)
2
>>> hash(object())
8736272801544
它是否将所有内容(对象、字符串、数字等)都视为对象?
您只是使用hash 函数将每个字典键表示为一个整数。该整数仅用于在底层字典数组中进行索引。假设字典以预先分配的大小 8 开始,我们使用模运算符(余数)将其放入适当的位置:
>>> hash('a')
12416037344
>>> hash(object()) % 8
2
所以在这种特殊情况下,散列对象被放置在底层数组的索引 2 中。当然可能会有冲突,因此根据底层实现,底层数组实际上可能是一个数组数组。
请注意,不可哈希的项目不能用作字典键:
>>> hash({})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
证明:
>>> d = {}
>>> d[{}] = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
【讨论】:
hash('') == hash(0) → True,但是len({'': type(''), 0: type(0)}) → 2。
我认为它可以工作很长时间,该对象支持__hash__ 方法,并且两个对象的__hash__(self) 返回相同的值,__eq__ 返回 True。 hashable 对象在这里解释。
例如。尝试关注
a = []
a.__hash__ == None # True
aa = 'xyz'
aa.__hash__ == None # False
a = (1,1,) # A Tuple, hashable
a.__hash__ == None # False
希望有帮助
【讨论】:
类型在 Python 中的使用方式与静态类型语言不同。可散列对象只是具有有效散列方法的对象。解释器只是调用该方法,没有类型检查或任何东西。从那时起,标准的哈希映射原则就适用了:一个对象要履行合约,它必须同时实现 hash 和 equals 方法。
【讨论】: