如何在Python中重写int等内置类型的哈希函数?
如何规避Python中int哈希值等于自身导致的哈希冲突?
核心结论
Python的内置类型(如int)的特殊方法(包括__hash__)是受语言层面保护的,无法直接修改属性——这就是你执行int.__hash__ = my_hash时触发TypeError的原因,CPython不允许修改内置扩展类型的属性。
可行解决方案
方案1:用自定义包装类封装int
创建一个轻量包装类,将int值包裹起来,重写__hash__和__eq__方法,既实现自定义哈希逻辑,又保证键的相等性判断符合dict的要求。
示例代码:
class WrappedInt: def __init__(self, value): self.value = int(value) def __eq__(self, other): # 支持与同类实例或原生int的相等判断 if isinstance(other, WrappedInt): return self.value == other.value return self.value == other def __hash__(self): # 替换为你需要的哈希逻辑,比如你最初尝试的tuple哈希 return hash((self.value,)) # 可选:添加调试友好的字符串表示 def __repr__(self): return f"WrappedInt({self.value})"
适配你的场景使用:
t, n = 1, 2 * 10 ** 5 mask = (1 << 17) - 1 fill = int((1 << 15) * 1.3 + 1) arr = [] arr += [WrappedInt(mask + 2)] * 2 x = 6 for i in range(1, fill): arr += [WrappedInt(x)] + [WrappedInt(x)] x = x * 5 + 1 x = x & mask arr += [WrappedInt(1)] * (n - len(arr))
后续将这些WrappedInt实例作为dict的键,就会使用自定义哈希逻辑,分散原int集中的哈希值,减少冲突。
方案2:自定义哈希映射类(替代原生dict)
如果不想修改所有int的使用方式,可以实现一个模拟dict行为的类,对int类型键单独应用自定义哈希逻辑。注意:此方案需要额外处理键的相等性判断,避免不同键因哈希碰撞被误判为同一键。
示例代码:
class CustomHashDict: def __init__(self): self._inner_dict = {} def _get_hash(self, key): if isinstance(key, int): return hash((key,)) # 非int类型保留原生哈希逻辑 return hash(key) def __setitem__(self, key, value): # 用(哈希值, 原键)作为内部存储的键,避免哈希碰撞导致的键冲突 self._inner_dict[(self._get_hash(key), key)] = value def __getitem__(self, key): target_hash = self._get_hash(key) for stored_hash, stored_key in self._inner_dict: if stored_hash == target_hash and stored_key == key: return self._inner_dict[(stored_hash, stored_key)] raise KeyError(key) def __contains__(self, key): target_hash = self._get_hash(key) for stored_hash, stored_key in self._inner_dict: if stored_hash == target_hash and stored_key == key: return True return False
注意:该方案的查找性能会弱于原生dict,适合数据量不大或无法修改原有int使用逻辑的场景。
补充说明
你的测试代码生成的整数会因mask限制和生成逻辑,集中在特定数值范围内,而int哈希等于自身的特性会导致dict哈希表出现大量冲突。使用包装类方案可以从根源上改变这些值的哈希分布,彻底解决冲突问题。
内容的提问来源于stack exchange,提问作者larticho
相关产品推荐
相关产品推荐

