python 类型提示,返回与输入相同的类型

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

我正在考虑一种情况,我有一个带有(几个)孩子的基类。我有一个函数,它接受基类对象的列表,并返回一个包含这些对象的新列表。

现在,如果我使用子类,显然返回的是这些子类对象的列表:考虑以下简单情况:

from typing import Sequence, List, TypeVar


class BaseClass:
    def __init__(self, data=None, *args, **kwargs):
        super().__init__()
        self.CanCalculate = True
        if data is None:
            data = []
            self.CanCalculate = False
        self._mydata = list(data)
        self.multiplier = 1

    @property
    def data(self):
        return self._mydata


class ChildClass(BaseClass):
    def sum_mul_data(self):
        return self.multiplier * sum(self.data)


class SecondChildClass(BaseClass):
    def sum_div_data(self):
        return sum(self.data) / self.multiplier


def myFun(input: Sequence[BaseClass]) -> List[BaseClass]:
    out = []
    for n, i in enumerate(input):
        if i.CanCalculate:
            i.multiplier = 10**n
            out.append(i)
    return out


childs = [ChildClass([1,2,3,4]), ChildClass(), ChildClass([1,2,3,4])]

t = myFun(childs)
for idx in t:
    print(idx.sum_mul_data())


childs = [SecondChildClass([1,2,3,4]), SecondChildClass(), SecondChildClass([1,2,3,4])]

t = myFun(childs)
for idx in t:
    print(idx.sum_div_data())

合法代码:但是 pycharm(和标准类型提示)在静态代码分析期间显示错误: “未解析的属性引用”@

idx.sum_mul_data()

现在显然这是由于 pycharm 认为函数的返回类型是“BaseClass”——而不是子类型。那么我该如何声明:“返回与输入相同的类型”?

我尝试使用类型变量:

T = TypeVar("T", BaseClass)
,尽管这给出了一个实际错误,即单个约束不能在
TypeVar
中使用。有趣的是,使用
T = TypeVar("T", BaseClass, ChildClass)
确实有效,并且 pycharm 正确推导了 sum_div_data 的类型(提示)。

python pycharm python-typing
1个回答
18
投票

您应该使用带有上限的类型变量:使用

T = TypeVar('T', bound=BaseClass)
而不是
T = TypeVar('T', BaseClass)

详情:

  • 当您执行类似

    T = TypeVar('T', ClassA, ClassB, ClassC...)
    之类的操作时,您正在创建一个具有值限制的类型变量。也就是说,您坚持认为
    T
    必须正是您列出的课程之一。

    这就是为什么不允许使用

    T = TypeVar('T', ClassA)
    的原因:typevar 只能等于一个类,所以你最好直接使用
    ClassA
    类型。

  • 当您执行类似

    T = TypeVar('T', bound=ClassA)
    之类的操作时,您正在创建一个具有上限的类型变量。您坚持认为
    T
    必须是
    ClassA
    或其任何子类。

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