You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否替换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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:12:25