能否替换Python字典的内置hash()方法以实现自定义哈希?
问题
我正在编写一个利用局部敏感哈希(Locality Sensitivity Hashing)和CityHash对字符串(Kmers)进行双重哈希的程序,用于检测长基因序列间的相似性。目前已实现核心功能,但希望通过修改Python字典的固有哈希逻辑、使用自定义DoubleHash函数来提升效率并减少冗余。我已实现继承UserDict的CustomDict类,现想了解是否可以直接替换Python内置的hash()方法,而非仅通过继承字典类实现。
相关代码如下:
DoubleHash函数
def DoubleHash(self, rawShingle: str) -> int: ''' Subsampling the shingle and hashing it to yield the same hash value for very similar shingles ''' subSet = '' for i in self.randList: subSet += rawShingle[i] hash_value = CityHash32(subSet) return hash_value
其中self.randList是抽取原字符串子样本的随机索引列表,目的是刻意制造哈希碰撞,让相似字符串映射到同一哈希值。
CustomDict类
class CustomDict(UserDict): def __setitem__(self, key, value) -> None: ''' Sets Hash:[Kmer, ] pair to dictionary ''' key = CityHash32(key) if key in self.data: self.data[key].append(value) else: self.data[key] = [value, ] return def __getitem__(self, key: int) -> list: ''' Gets list of Kmers corresponding to Hash ''' try: return self.data[key] except KeyError: pass raise KeyError(key) def __getkey__(self, value: list) -> int: ''' Gets Hash corresponding to list of Kmers ''' for i, k in enumerate(self.data.keys()): if value in self.data[k]: index = i break return list(self.data.keys())[index]
回答
不能直接替换Python全局的内置hash()方法,原因如下:
hash()是Python全局内置函数,修改它会影响所有依赖哈希逻辑的内置结构(如dict、set、frozenset等),引发不可预料的全局行为,严重时会破坏整个程序的稳定性。- 全局修改会污染命名空间,干扰其他模块、第三方库的正常运行,这在实际开发中是严格不推荐的做法。
针对你的需求,推荐以下两种更合理的实现方案:
1. 基于现有CustomDict类改造
你当前继承UserDict的思路是可行的,只需将__setitem__中的CityHash32替换为自定义的DoubleHash函数,即可让字典内部使用目标哈希逻辑,且不会影响其他代码:
def __setitem__(self, key, value) -> None: ''' Sets Hash:[Kmer, ] pair to dictionary ''' key = self.DoubleHash(key) # 替换为自定义DoubleHash if key in self.data: self.data[key].append(value) else: self.data[key] = [value, ] return
这种方式隔离性强,仅在你的自定义字典类中生效,不会干扰全局代码。
2. 自定义Key类并重载__hash__方法
如果不想继承字典,可给Kmer字符串包装一个自定义类,在类内重载__hash__方法使用DoubleHash,同时重载__eq__方法配合局部敏感哈希的逻辑(哈希碰撞后需判断是否真的“相似”):
class KmerKey: def __init__(self, kmer: str, randList): self.kmer = kmer self.randList = randList def __hash__(self): subSet = ''.join([self.kmer[i] for i in self.randList]) return CityHash32(subSet) def __eq__(self, other): # 根据需求定义“相似”判断逻辑,示例为比较子样本是否一致 if not isinstance(other, KmerKey): return False self_sub = ''.join([self.kmer[i] for i in self.randList]) other_sub = ''.join([other.kmer[i] for i in other.randList]) return self_sub == other_sub
之后使用普通Python字典时,直接用KmerKey实例作为key即可,字典会自动调用你重载的__hash__和__eq__方法。
额外注意事项
- 局部敏感哈希的核心是刻意制造碰撞,但必须保证
__eq__方法与哈希逻辑匹配,否则字典会出现逻辑错误(如哈希相同但实际不应视为“相等”的情况)。 - 当前
CustomDict的__getkey__方法效率极低(遍历所有键),若需频繁反向查询(从Kmer列表找哈希),建议维护一个反向字典存储映射关系,提升查询速度。
内容的提问来源于stack exchange,提问作者Visnu S Pandian
相关产品推荐
相关产品推荐

