Python类型注释:继承方法的返回类型

3
我已经创建了一个类似字典的自定义类,以简化在大型数据集上合并评估指标的过程。该类实现了一个 __add__ 方法来汇总各种指标。
以下是我正在处理的代码的简化版本:
from __future__ import annotations
from typing import TypeVar, Dict


T = TypeVar('T', int, float)


class AddableDict(Dict[str, T]):
    def __add__(self, other: AddableDict[T]) -> AddableDict[T]:
        if not isinstance(other, self.__class__):
            raise ValueError()
        new_dict = self.__class__()
        all_keys = set(list(self.keys()) + list(other.keys()))
        for key in all_keys:
            new_dict[key] = self.get(key, 0) + other.get(key, 0)
        return new_dict


# AddableIntDict = AddableDict[int]
# this would work just fine, however I need to add a few additional methods


class AddableIntDict(AddableDict[int]):
    def some_int_specific_method(self) -> None:
        pass


def main() -> None:
    x = AddableIntDict()
    y = AddableIntDict()
    x['a'] = 1
    y['a'] = 3

    x += y  # breaks mypy

程序的最后一行导致了mypy (0.782)出现以下错误:error: Incompatible types in assignment (expression has type "AddableDict[int]", variable has type "AddableIntDict")
我能理解这个错误。
当我把AddableIntDict定义为AddableDict[int]类型别名时,代码可以正常工作,如我的注释所示。但是,由于我需要根据字典值的类型添加其他方法,如some_int_specific_method所示,因此我不能简单地使用类型别名。
是否有人能够指导我如何注释父类的__add__方法,以便它将返回调用类的类型呢?
(我正在使用Python 3.8.3)

2
顺便提一下,all_keys = set(list(self.keys()) + list(other.keys())) 可以简化为 all_keys = self.keys() | other.keys(),因为字典的键视图对象已经实现了类似集合的操作。 - juanpa.arrivillaga
1
另外,作为另一个侧面的说明,看起来这只是在重新发明 collections.Counter - juanpa.arrivillaga
感谢 @juanpa.arrivillaga 的提示。我熟悉 Counter。我正在实现的类引入了更复杂的逻辑,尽管它可能可以重写为使用 Counter - tingled
1个回答

6

通过使用类型变量,可以引用“self的类型”。这将解析为在调用方法的基类或子类中适当的类型:

from typing import TypeVar, Dict


T = TypeVar('T', int, float)
AD = TypeVar('AD', bound='AddableDict')


class AddableDict(Dict[str, T]):
    def __add__(self: AD, other: AD) -> AD: ...


class AddableIntDict(AddableDict[int]):
    def some_int_specific_method(self) -> None: ...

x = AddableIntDict(a=1)
y = AddableIntDict(a=3)
x += y  # works for mypy and others

1
注意:使用--strict标志时,mypy会报错,指出“AddableDict”缺少泛型类型参数。但是似乎可以安全地忽略这些错误。 - Peilonrayz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接