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

Python重写dict的__hash__方法触发mypy兼容错误的解决方案

解决办法

方案1:使用组合而非继承(推荐)

直接继承dict会因为其__hash__被设为None导致mypy报错,改用组合方式,内部维护一个dict实例,自己实现必要的映射方法和__hash__,完全避开继承冲突:

from typing import Generic, Iterator, KEY, VALUE

class HashableBinnerDict(Generic[KEY, VALUE]):
    def __init__(self, *args, **kwargs):
        self._data = dict[KEY, VALUE](*args, **kwargs)
        self._is_frozen = False  # 可选:防止哈希后修改实例

    def __getitem__(self, key: KEY) -> VALUE:
        return self._data[key]

    def __setitem__(self, key: KEY, value: VALUE) -> None:
        if self._is_frozen:
            raise ValueError("Cannot modify instance after hashing")
        self._data[key] = value

    def __delitem__(self, key: KEY) -> None:
        if self._is_frozen:
            raise ValueError("Cannot modify instance after hashing")
        del self._data[key]

    def __iter__(self) -> Iterator[KEY]:
        return iter(self._data)

    def __len__(self) -> int:
        return len(self._data)

    def __hash__(self) -> int:
        self._is_frozen = True  # 哈希后标记为不可修改
        return hash(frozenset(self._data.items()))

    # 可选:实现常用的dict方法以保持接口一致
    def items(self):
        return self._data.items()

    def keys(self):
        return self._data.keys()

    def values(self):
        return self._data.values()

这种方式不仅解决了mypy的报错,还遵循了"组合优于继承"的设计原则,同时可以通过_is_frozen标记避免可变实例哈希后修改导致的异常行为。

方案2:继承抽象基类MutableMapping

继承collections.abc.MutableMapping而非dict,该抽象基类定义了映射类型的标准接口,且其__hash__未被设为None,因此重写__hash__不会触发mypy的override错误:

from typing import Generic, KEY, VALUE
from collections.abc import MutableMapping

class HashableBinnerDict(MutableMapping[KEY, VALUE], Generic[KEY, VALUE]):
    def __init__(self, *args, **kwargs):
        self._data = dict[KEY, VALUE](*args, **kwargs)
        self._is_frozen = False

    def __getitem__(self, key: KEY) -> VALUE:
        return self._data[key]

    def __setitem__(self, key: KEY, value: VALUE) -> None:
        if self._is_frozen:
            raise ValueError("Cannot modify instance after hashing")
        self._data[key] = value

    def __delitem__(self, key: KEY) -> None:
        if self._is_frozen:
            raise ValueError("Cannot modify instance after hashing")
        del self._data[key]

    def __iter__(self):
        return iter(self._data)

    def __len__(self) -> int:
        return len(self._data)

    def __hash__(self) -> int:
        self._is_frozen = True
        return hash(frozenset(self._data.items()))

MutableMapping会自动为你实现keys()、values()、items()等常用方法,只需实现5个核心方法即可,代码更简洁。

关键注意事项

可变对象实现__hash__存在风险:如果实例在哈希后被修改,其哈希值会变化,导致它在集合或字典中无法被正确查找。上述方案中加入的_is_frozen标记可以在哈希后禁止修改,避免此类问题。

内容的提问来源于stack exchange,提问作者Mattia Surricchio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:27:36