Python:混合键类型的dict如何工作?

时间:2015-05-31 04:12:52

标签: python

我知道以下内容在Python中有效:foo = {'a': 0, 1: 2, some_obj: 'c'}

然而,我不知道内部如何运作。它是否将对象(对象,字符串,数字等)视为对象?是否键入check以确定如何计算给定密钥的哈希码?

5 个答案:

答案 0 :(得分:5)

类型在Python中的使用方式与静态类型语言不同。可散列对象只是一个具有有效散列方法的对象。解释器只调用该方法,不进行类型检查或任何操作。从那时起,标准哈希映射原则适用:对于要完成契约的对象,它必须实现哈希和等于方法。

答案 1 :(得分:3)

您可以通过打开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'

答案 2 :(得分:1)

Python中的所有内容都是一个对象,每个具有__hash__方法的对象都可以用作字典键。因此,为每个可能的键返回一个唯一的整数的方法(尝试)究竟是如何特定于每个类,并且有点私有(使用该术语不小心用于幽默效果)。有关详细信息,请参阅https://wiki.python.org/moin/DictionaryKeys

(在完全可以清除之前,您的类需要支持其他几种方法。再次,请参阅链接的说明。)

答案 3 :(得分:0)

我认为它会工作很长时间,对象支持__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

希望有所帮助

答案 4 :(得分:0)

暂时忽略字典可能更容易,只想到集合。您可以看到一组s可能包含{'a', 1, some_object},对吗?如果您尝试将1添加到此集合中,它将无法执行任何操作(因为1已存在)?

现在,假设您尝试向another_object添加sanother_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,您应该记住,dict中只允许使用可清洗对象。但这本身就是一个不同的主题,而不是你问题的关键,AFAICT