标准库里的所有映射类型都是利用 dict 来实现的,因此它们有个共同的限制,即只有可散列的数据类型才能用作这些映射里的键,本文记录Python 中 hash 相关内容。
Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
__hash__()
方法) ,并且可以与其他对象进行比较(它需要一个 _ eq _ ()方法) ,那么该对象就是可变的。比较相等的 hasable 对象必须具有相同的散列值。
Hashability 使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值。
Python 中大多数不可变的内置对象都是 hasable; 可变的容器(如列表或字典)则不是; 不可变的容器(如元组和 frozenset)只有在其元素是 hasable 的情况下才是 hasable 的。默认情况下,作为用户定义类实例的对象是可以 hasable 的。它们都比较 unequal (除了它们自己) ,它们的 hash 值是从它们的 id ()派生出来的。__hash__()
方 法__qe__()
方法test = (1, 2, (30, 40))
print(hash(test))
tf = frozenset([30, 40])
print(hash(tf))
err = (1, 2, [30, 40])
print(hash(err))
-->
-3907003130834322577
-5140580174489706912
unhashable type: 'list'
File "G:\Active\Python_Practise\fluent python\chapter-2\core.py", line 8, in <module>
print(hash(err))
__hash__
。如 果两个对象在比较的时候是相等的,那它们的散列值必须相等,否 则散列表就不能正常运行了。__hash__()
方法所得到的散列 值是不变的。__eq__()
方法来检测相等性。a == b
为真,则 hash(a) == hash(b)
也为真。如果你实现了一个类的
__eq__
方法,并且希望它是可 散列的,那么它一定要有个恰当的__hash__
方法,保证在 a == b 为真的情况下 hash(a) == hash(b) 也必定为真。否则 就会破坏恒定的散列表算法,导致由这些对象所组成的字典和 集合完全失去可靠性,这个后果是非常可怕的。另一方面,如 果一个含有自定义的__eq__
依赖的类处于可变的状态,那就 不要在这个类中实现__hash__
方法,因为它的实例是不可散 列的。
记住我们现在讨论的是空间优化。如果你手头有几百万个对象,而你的机器有几个 GB 的内存,那么空间的优化工作可以等到真正需 要的时候再开始计划,因为优化往往是可维护性的对立面。
dict([key1, value1), (key2, value2)]
和 dict([key2, value2], [key1, value1])
得到的两个字典,在进行比较的时候,它们是相等的;但是如果在 key1 和 key2 被添加到字典里的过程中有冲突发生的话,这两个键出现在字典里的顺序是不一样 的。扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有