Hashability in Python
Introduction
hashable
An object is hashable if it has a hash value which never changes during its lifetime (it needs a
__hash__()
method), and can be compared to other objects (it needs an__eq__()
method). Hashable objects which compare equal must have the same hash value.Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.
Most of Python’s immutable built-in objects are hashable; mutable containers (such as lists or dictionaries) are not; immutable containers (such as tuples and frozensets) are only hashable if their elements are hashable. Objects which are instances of user-defined classes are hashable by default. They all compare unequal (except with themselves), and their hash value is derived from their
id()
.--From the Python glossary
Which Objects Are Hashable and Which Are Not
我们知道 set
的元素和 dict
的键 key 要求是
hashable 的,因此我通过了 set
测试,得出如下结果:
Hashable data types: int, float, str, tuple, and NoneType. Unhashable data types: dict, list, and set.
测试过程:
1 | In [1]: test_set=set() |
What Does Hashable Mean
Hashable: A characteristic of a Python object to indicate whether the object has a hash value, which allows the object to serve as a key in a dictionary or an element in a set.
Python 实现了内置的 hash 函数:hash()
,来生成的对象的
hash。例如:
1 | In [13]: hash("Hello") |
Customize Hashability
By default, all instances of custom classes will have a hash value defined at creation and it will not change over time. Two instances of the same class will have two different hash values.
You will see that the hash value that you get from your objects changes every time you run the code. This is because the hash is derived from the object's id. Python, as expected, allows you to define your own hash value.
By default, custom class instances are compared by comparing their identities using the built-in id() function. That's why two object with the same attribute value isn't the same one from the set or dictionaries perspective.
结论: Dictionaries and set check two things: the hash
value(The return value of self.__hash__
) and
the equality(self.__eq__
)
实验:
1 | #!/usr/bin/env python |
无论有无 __hash__()
时,结果都为:集合将两个相同属性值的对象看作是不同的对象。
从下面结果可以看出。 set
通过执行
__hash__()
检查了对象的 hash
1 | # violetv at manjaro in ~/test [21:03:54] |
当我们在上述代码的对象中添加了 __eq__()
函数之后,我们可以看到了 set 已经将两个对象识别为一个了。
1 | def __eq__(self, other): |
1 | $ python hashable.py |
参考资料
What are Hashable Objects > What the difference between hash-able and immutable > 3 Essential Questions About Hashable in Python > Python Glossary