【问题标题】:Typing dict mixin class with Mypy使用 Mypy 键入 dict mixin 类
【发布时间】:2019-04-12 17:57:58
【问题描述】:

我正在尝试编写一个小的 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'

我不知道怎么了:(

【问题讨论】:

    标签: python dictionary multiple-inheritance mixins mypy


    【解决方案1】:

    这似乎是 mypy 中的一个错误——请参阅 mypy 用于分析使用多重继承的类的 MRO 的代码中的 this TODO。简而言之,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。

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

    (当然,您可以随时尝试自己提供修复!)

    【讨论】:

    • 嗯,问题已解决,您的 mypy 源链接已损坏(因为您已链接到 master!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 2018-09-07
    • 2020-11-13
    • 2020-05-31
    • 2022-07-31
    • 2011-07-10
    • 2020-12-21
    相关资源
    最近更新 更多