Python hash 函数
上次修改时间:2025 年 4 月 11 日
本综合指南探讨 Python 的 hash
函数,该函数返回对象的哈希值。我们将介绍基本用法、可哈希类型、自定义对象以及 Python 中哈希的实际示例。
基本定义
hash
函数返回一个整数,表示对象的哈希值。哈希值用于快速比较字典键和集合成员。
关键特征:适用于不可变对象,在对象的生命周期内(每个 Python 会话)返回相同的值,对于不可哈希的类型引发 TypeError。不保证哈希值是唯一的。
内置类型的基本用法
这是一个简单的用法,使用不同的内置类型,展示了 hash
如何处理数字、字符串和元组。
# With integers print(hash(42)) # 42 print(hash(-100)) # -100 # With floats print(hash(3.14)) # 322818021289917443 # With strings print(hash("hello")) # -1267296259 # With tuples (immutable) print(hash((1, 2, 3))) # 529344067295497451
此示例显示了 hash
与不同不可变类型的使用。整数通常哈希到它们本身,而其他类型则产生更复杂的值。
请注意,由于安全原因,随机哈希种子,哈希值可能因 Python 运行和版本而异。
不可哈希的类型
像列表和字典这样的可变类型是不可哈希的。此示例显示了尝试哈希它们时会发生什么。
try: print(hash([1, 2, 3])) except TypeError as e: print(f"Error: {e}") # unhashable type: 'list' try: print(hash({"a": 1})) except TypeError as e: print(f"Error: {e}") # unhashable type: 'dict'
这些示例演示了 hash
对可变类型的行为。列表和字典会引发 TypeError
,因为它们可以更改。
要使可变对象可哈希,您需要使其不可变(例如,将列表转换为元组)或实现自定义哈希逻辑。
带有 __hash__ 的自定义对象
您可以通过实现 __hash__
方法使自定义对象可哈希。此示例创建一个 Point 类。
class Point: def __init__(self, x, y): self.x = x self.y = y def __hash__(self): return hash((self.x, self.y)) def __eq__(self, other): return self.x == other.x and self.y == other.y def __repr__(self): return f"Point({self.x}, {self.y})" p1 = Point(1, 2) p2 = Point(1, 2) print(hash(p1)) # Same as hash((1, 2)) print(hash(p2)) # Same as hash(p1)
Point 类使用其坐标的哈希值实现 __hash__
。当我们在 Point 实例上调用 hash
时,Python 会使用此方法。
请注意,比较相等的对象应具有相同的哈希值,因此 __eq__
的实现也很重要。
会话内的哈希一致性
哈希值在一个 Python 会话中保持一致,但可能会在运行之间发生变化。此示例演示了此行为。
s = "Python" h1 = hash(s) h2 = hash(s) print(h1 == h2) # True within same session # Restart Python and hash may be different print("Hash value in this run:", h1)
这表明哈希值在单个 Python 会话期间保持不变。但是,由于哈希随机化,它们可能在运行之间有所不同。
哈希随机化是一项安全功能,可防止某些类型的拒绝服务攻击。
数据结构中的实际用法
哈希是 Python 字典和集合的基础。此示例显示了哈希值如何实现高效查找。
# Dictionary relies on hash values d = {"apple": 1, "banana": 2} print("apple" in d) # Fast lookup using hash # Set uses hashing for membership tests s = {1, 2, 3, 4, 5} print(3 in s) # Fast lookup using hash # Custom objects in sets points = {Point(1, 2), Point(3, 4)} print(Point(1, 2) in points) # True
这演示了哈希值如何实现字典和集合中的高效成员资格测试。相同的原则适用于自定义对象。
对于自定义对象,要在集合/字典中正确工作,必须正确实现 __hash__
和 __eq__
。
最佳实践
- 使用不可变对象: 仅哈希不可变对象
- 实现 __hash__ 和 __eq__: 对于自定义可哈希类型
- 不要依赖特定的哈希值: 它们在运行之间会发生变化
- 考虑性能: 简单的哈希函数更快
- 保持哈希一致性: 相等的对象必须具有相同的哈希值
资料来源
作者
列出所有 Python 教程。