python - 使用 Mypy 键入 dict mixin 类

标签 python dictionary multiple-inheritance mixins mypy

我正在尝试编写一个小的 mixin 类来在某种程度上桥接 Set 和 MutableMapping 类型:我希望映射类型能够接收一些对象(字节),对它们进行哈希处理并存储它们,以便它们可以访问散列。

这是将此类与标准 dict 混合的工作版本:

from hashlib import blake2b

class HashingMixin:
    def add(self, content):
        digest = blake2b(content).hexdigest()
        self[digest] = content

class HashingDict(dict, HashingMixin):
    pass

但是我不知道如何添加类型注释。

来自 https://github.com/python/mypy/issues/1996似乎 mixin 必须子类化 abc.ABCabc.abstractmethod - 定义它期望调用的所有方法,所以这是我的镜头:

import abc
from hashlib import blake2b
from typing import Dict

class HashingMixin(abc.ABC):
    def add(self, content: bytes) -> None:
        digest = blake2b(content).hexdigest()
        self[digest] = content

    @abc.abstractmethod
    def __getitem__(self, key: str) -> bytes:
        raise NotImplementedError

    @abc.abstractmethod
    def __setitem__(self, key: str, content: bytes) -> None:
        raise NotImplementedError


class HashingDict(Dict[str, bytes], HashingMixin):
    pass

然后 Mypy 提示 HashingDict 定义:

error: Definition of "__getitem__" in base class "dict" is incompatible with definition in base class "HashingMixin"
error: Definition of "__setitem__" in base class "dict" is incompatible with definition in base class "HashingMixin"
error: Definition of "__setitem__" in base class "MutableMapping" is incompatible with definition in base class "HashingMixin"
error: Definition of "__getitem__" in base class "Mapping" is incompatible with definition in base class "HashingMixin"

显示类型:

reveal_type(HashingMixin.__getitem__)
reveal_type(HashingDict.__getitem__)

产量:

error: Revealed type is 'def (coup.content.HashingMixin, builtins.str) -> builtins.bytes'
error: Revealed type is 'def (builtins.dict[_KT`1, _VT`2], _KT`1) -> _VT`2'

不知道怎么回事:(

最佳答案

这似乎是 mypy 中的一个错误——参见 this TODO在代码中,mypy 用于分析使用多重继承的类的 MRO。简而言之,mypy 错误地完成了忽略您已使用具体值参数化 Dict 的操作,而是像使用 Dict 一样分析代码。

我相信https://github.com/python/mypy/issues/5973可能是问题跟踪器中最相关的问题:根本原因相同。

在修复该错误之前,您可以通过向任何有错误的行添加 # type: ignore 来抑制 mypy 在该行上生成的错误。因此,对于您的情况,您可以执行以下操作:

import abc
from hashlib import blake2b
from typing import Dict

class HashingMixin(abc.ABC):
    def add(self, content: bytes) -> None:
        digest = blake2b(content).hexdigest()
        self[digest] = content

    @abc.abstractmethod
    def __getitem__(self, key: str) -> bytes:
        raise NotImplementedError

    @abc.abstractmethod
    def __setitem__(self, key: str, content: bytes) -> None:
        raise NotImplementedError


class HashingDict(Dict[str, bytes], HashingMixin):  # type: ignore
    pass

如果您决定采用这种方法,我建议您还留下一条额外的评论,说明您为什么要抑制这些错误并使用 --warn-unused-ignores 标志运行 mypy。

前者是为了让你的代码的任何 future 读者受益;后者将使 mypy 在遇到 # type: ignore 时报告警告,该错误实际上并未抑制任何错误,因此可以安全地删除。

(当然,您始终可以尝试自己贡献修复!)

关于python - 使用 Mypy 键入 dict mixin 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55657271/

相关文章:

python - 使用Python将云语音API的结果导出到JSON文件

arrays - Swift:将一组字典扁平化为一个字典

java - 抽象类和多重继承

c++ - 从多个派生类返回一个函数

c++ - 如何从实现与其他接口(interface)共享的接口(interface)的类继承

python - 如何表示未使用的函数参数?

python - 如何避免 __init__ 中的 "self.x = x; self.y = y; self.z = z"模式?

python - Flask 模型 .save() 引发 TypeError : _validate() missing 1 required positional argument: 'value'

java - 覆盖哈希码方法时的HashMap性能

python - 用Python中的值更新字典列表中所有匹配的键