dict
里添加新键而又发生散列冲突的时候,新键可能会被安排存放到另一个位置。但字典是否等价则与键的添加次序无关。__slots__
属性可以改变实例属性的存储方式,由 dict
变成 tuple
。dict
和 set
背后:散列表in
查找一个数花费约三分之一微秒(0.000000337s)。使用列表需要 0.01s。hash()
方法可以用于所有的内置类型对象。如果是自定义对象调用 hash()
的话,实际上运行的是自定义的 __hash__
。1 == 1.0
为真,那么 hash(1) == hash(1.0)
也必须为真。str
、bytes
和 datetime
对象的散列值计算过程中多了随机的“加盐”这一步。所加盐值是 Python 进程内的一个常量,但是每次启动 Python 解释器都会生成一个不同的盐值。随机盐值的加入是为了防止 DOS 攻击而采取的 一种安全措施。my_dict[search_key]
背后的值,Python 首先会调用 hash(search_key)
来计算 search_key
的散列值,把这个值最低的几位数字当作偏移量,在散列表里查找表元(具体取几位,得看当前散列表的大小)。若找到的表元是空的,则抛出 KeyError
异 常。若不是空的,则表元里会有一对 found_key:found_value
。 这时候 Python 会检验 search_key == found_key
是否为真,如果它们相等的话,就会返回 found_value
。若发生散列冲突,则会在散列值取另一部分,来得散列表中的另一行。hash()
函数,并且通过 __hash__()
方法所得到的散列值是不变的。__eq__()
方法来检测相等性。a == b
为真,则 hash(a) == hash(b)
也为真。 所有由用户自定义的对象默认都是可散列的,因为它们的散列值由 id()
来获取,而且它们都是不相等的。__eq__
方法,并且希望它是可散列的,那么它一定要有个恰当的 __hash__
方法,保证在 a == b
为真的情况下 hash(a) == hash(b)
也必定为真。另一方面,如果一个含有自定义的 __eq__
依赖的类处于可变的状态,那就不要在这个类中实现 __hash__
方法,因为它的实例是不可散列的。