多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# Python 哈希教程 > 原文: [http://zetcode.com/python/hashing/](http://zetcode.com/python/hashing/) Python 哈希教程解释了 Python 中的哈希概念。 我们介绍了哈希表和 Python 可哈希对象。 ## 哈希表 哈希表用于以许多常见的编程语言(例如 C++ ,Java 和 Python)实现映射和设置数据结构。 Python 将哈希表用于字典和集合。 哈希表是键值对的无序集合,其中每个键都是唯一的。 哈希表提供了有效的查找,插入和删除操作的组合。 这些是数组和链表的最佳属性。 ## 哈希 哈希是使用算法将任意大小的数据映射到固定长度的过程。 这称为哈希值。 哈希用于创建高性能,直接访问的数据结构,在该结构中要快速存储和访问大量数据。 哈希值使用哈希函数计算。 ## Python 可哈希对象 如果对象的哈希值在其生命周期内从未发生变化,则该对象是可哈希的。 (在多次调用 Python 程序期间,它可以具有不同的值。)可哈希对象需要`__hash__()`方法。 为了执行比较,哈希需要一种`__eq__()`方法。 > **注意**:比较相等的可哈希对象必须具有相同的哈希值。 哈希性使对象可用作字典键和集成员,因为这些数据结构在内部使用哈希值。 Python 不可变的内置对象是可哈希的; 可变容器(例如列表或字典)不是。 默认情况下,作为用户定义类实例的对象是可哈希的。 它们都比较不相等(除了它们本身),并且它们的哈希值是从`id()`派生的。 > **注意**:如果一个类没有定义一个`__eq __()`方法,它也不应该定义一个`__hash __()`操作。 如果它定义了`__eq __()`而不是`__hash __()`,则其实例将不能用作可哈希集合中的项目。 ## Python `hash()`函数 `hash()`函数返回对象的哈希值(如果有的话)。 哈希值是整数。 它们用于在字典查找期间快速比较字典关键字。 对象可以实现`__hash__()`方法。 ## Python 不可变内置函数可哈希化 Python 不变的内置函数(例如整数,字符串或元组)是可哈希的。 `builtin_hashables.py` ```py #!/usr/bin/env python3 val = 100 print(val.__hash__()) print("falcon".__hash__()) print((1,).__hash__()) ``` 该示例显示三个哈希值的值:整数,字符串和元组。 ## Python 自定义可哈希对象示例 I Python 自定义对象默认情况下是可哈希的。 他们的哈希值是从其 ID 派生的。 `custom_object.py` ```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`的两个实例。 ```py u1 = User('John Doe', 'gardener') u2 = User('John Doe', 'gardener') ``` 我们有两个具有相同数据的实例。 ```py print('hash of user 1') print(hash(u1)) ``` `hash()`函数返回对象的哈希值。 默认实现是从对象的 ID 派生的。 ```py $ python custom_object.py hash of user 1 -9223371894419573195 hash of user 2 142435202673 different users ``` 即使用户详细信息相同,但比较仍会产生不同的对象。 为了更改它,我们需要实现`__eq__()`方法。 ## Python 自定义可哈希对象示例 II 在第二个示例中,我们实现了自定义`__eq__()`方法。 `custom_object2.py` ```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` ```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 集中,当以后更改属性时,我们将获得预期的输出。 ```py def __hash__(self): return hash((self.name, self.occupation)) ``` `__hash__()`函数的实现从属性元组返回使用`hash()`函数计算的哈希值。 ```py $ 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` ```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`装饰器。 ```py $ python decorator.py same user User(name='John Doe', occupation='gardener') == User(name='John Doe', occupation='gardener') 1 ``` 这是输出。 在本教程中,我们介绍了 Python 中的哈希。 您可能也对以下相关教程感兴趣: [Python 教程](/lang/python/), [Python 列表推导](/articles/pythonlistcomprehensions/)或列表[所有 Python 教程](/all/#python)。