用Mypy键入dict mixin类

问题描述 投票:2回答:1

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

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

(当然,你总是可以自己动手修复!)

© www.soinside.com 2019 - 2024. All rights reserved.