我知道以下内容在Python中有效:foo = {'a': 0, 1: 2, some_obj: 'c'}
然而,我不知道内部如何运作。它是否将对象(对象,字符串,数字等)视为对象?是否键入check以确定如何计算给定密钥的哈希码?
答案 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
添加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,您应该记住,dict中只允许使用可清洗对象。但这本身就是一个不同的主题,而不是你问题的关键,AFAICT