Python 哈希教程
Python 哈希教程 解释了 Python 中的哈希概念,介绍了哈希表和 Python 可哈希对象。
哈希表
哈希表用于以许多常见的编程语言(例如 C++ ,Java 和 Python)实现映射和设置数据结构。 Python 将哈希表用于字典和集合。 哈希表是键值对的无序集合,其中每个键都是唯一的。 哈希表提供了有效的查找,插入和删除操作的组合。 这些是数组和链接列表的最佳属性。
散列
哈希是使用算法将任意大小的数据映射到固定长度的过程。 这称为哈希值。 散列用于创建高性能,直接访问的数据结构,在该结构中要快速存储和访问大量数据。 哈希值使用哈希函数计算。
Python 可哈希对象
如果对象的哈希值在其生命周期内从未发生变化,则该对象是可哈希的。 (在多次调用 Python 程序期间,它可以具有不同的值。)可哈希对象需要__hash__()
方法。 为了执行比较,散列需要一种__eq__()
方法。
Note: Hashable objects which compare equal must have the same hash value.
散列性使对象可用作字典键和 set 成员,因为这些数据结构在内部使用散列值。 Python 不可变的内置对象是可哈希的; 可变容器(例如列表或字典)不是。 默认情况下,作为用户定义类实例的对象是可哈希的。 它们都比较不相等(除了它们本身),并且它们的哈希值是从id()
派生的。
Note: If a class does not define an __eq__()
method it should not define a __hash__()
operation either; if it defines __eq__()
but not __hash__()
, its instances will not be usable as items in hashable collections.
Python hash()
函数
hash()
函数返回对象的哈希值(如果有的话)。 哈希值是整数。 它们用于在字典查找期间快速比较字典关键字。 对象可以实现__hash__()
方法。
Python 不可变内置函数可哈希化
Python 不变的内置函数(例如整数,字符串或元组)是可哈希的。
builtin_hashables.py
| #!/usr/bin/env python3
val = 100
print(val.__hash__())
print("falcon".__hash__())
print((1,).__hash__())
|
该示例显示三个哈希值的值:整数,字符串和元组。
Python 自定义可哈希对象示例 I
Python 自定义对象默认情况下是可哈希的。 他们的哈希值是从其 ID 派生的。
custom_object.py
| #!/usr/bin/env python3
class User:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
u1 = User('John Doe', 'gardener')
u2 = User('John Doe', 'gardener')
print('hash of user 1')
print(hash(u1))
print('hash of user 2')
print(hash(u2))
if (u1 == u2):
print('same user')
else:
print('different users')
|
在示例中,我们有User
的两个实例。
| u1 = User('John Doe', 'gardener')
u2 = User('John Doe', 'gardener')
|
我们有两个具有相同数据的实例。
| print('hash of user 1')
print(hash(u1))
|
hash()
函数返回对象的哈希值。 默认实现是从对象的 ID 派生的。
| $ python custom_object.py
hash of user 1
-9223371894419573195
hash of user 2
142435202673
different users
|
即使用户详细信息相同,但比较仍会产生不同的对象。 为了更改它,我们需要实现__eq__()
方法。
Python 自定义可哈希对象示例 II
在第二个示例中,我们实现了自定义__eq__()
方法。
custom_object2.py
| #!/usr/bin/env python3
class User:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
def __eq__(self, other):
return self.name == other.name \
and self.occupation == other.occupation
def __str__(self):
return f'{self.name} {self.occupation}'
u1 = User('John Doe', 'gardener')
u2 = User('John Doe', 'gardener')
if (u1 == u2):
print('same user')
print(f'{u1} == {u2}')
else:
print('different users')
# users = {u1, u2}
# print(len(users))
|
现在比较返回给我们的预期输出; 但是,我们不能将对象插入 Python 集中; 这将导致TypeError: unhashable type: 'User'
。 为了更改此设置,我们实现了__hash__()
方法。
Python 自定义可哈希对象示例 III
在第三个示例中,我们实现了__eq__()
和__hash__()
方法。
custom_object3.py
| #!/usr/bin/env python3
class User:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
def __eq__(self, other):
return self.name == other.name \
and self.occupation == other.occupation
def __hash__(self):
return hash((self.name, self.occupation))
def __str__(self):
return f'{self.name} {self.occupation}'
u1 = User('John Doe', 'gardener')
u2 = User('John Doe', 'gardener')
users = {u1, u2}
print(len(users))
if (u1 == u2):
print('same user')
print(f'{u1} == {u2}')
else:
print('different users')
print('------------------------------------')
u1.occupation = 'programmer'
users = {u1, u2}
print(len(users))
if (u1 == u2):
print('same user')
print(f'{u1} == {u2}')
else:
print('different users')
|
该示例比较了具有__eq__()
和__hash__()
方法的自定义实现的两个对象。 可以将这些对象插入 Python 集中,当以后更改属性时,我们将获得预期的输出。
| def __hash__(self):
return hash((self.name, self.occupation))
|
__hash__()
函数的实现从属性元组返回使用hash()
函数计算的哈希值。
| $ python custom_object3.py
1
same user
John Doe gardener == John Doe gardener
------------------------------------
2
different users
|
Python @dataclass
装饰器
从 Python 3.7 开始,我们有了dataclass
装饰器,它会自动生成一些样板代码。
数据类装饰器的冻结参数(默认为False
)。 如果指定,则字段将被冻结(即只读)。 如果eq
设置为True
(默认情况下),则将实现__hash__()
方法,并且对象实例将是可哈希的。
decorator.py
| #!/usr/bin/env python3
from dataclasses import dataclass
@dataclass(frozen=True)
class User:
name: str
occupation: str
u1 = User('John Doe', 'gardener')
u2 = User('John Doe', 'gardener')
if (u1 == u2):
print('same user')
print(f'{u1} == {u2}')
else:
print('different users')
users = {u1, u2}
print(len(users))
|
该示例使用@dataclass
装饰器。
| $ python decorator.py
same user
User(name='John Doe', occupation='gardener') == User(name='John Doe', occupation='gardener')
1
|
在本教程中,我们介绍了 Python 中的哈希。