蟒蛇类型提示,返回相同类型的输入

问题描述:

嗯,我正在考虑一个案例,我有一个(几个)孩子的基类。我有一个函数,它接受一个基类对象列表,并返回一个新列表,其中包含这些对象。蟒蛇类型提示,返回相同类型的输入

现在,如果我会用一个子类明显的回报是这些子类对象的列表:考虑以下简单的情况:

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的” - 不是一个孩子。那么我将如何陈述:“返回与输入相同的类型”?

我试过使用typevar:T = TypeVar("T", BaseClass),虽然这给了一个实际的错误,但是一个单一的约束不能在TypeVar中使用。有趣的是,使用T = TypeVar("T", BaseClass, ChildClass)确实有效,pycharm正确推导出sum_div_data的类型(提示)。

+0

你似乎已经解决了你自己的问题。 Docs似乎认为'T = TypeVar(“T”)'会给你一个完全泛型的类型提示,正如你所看到的,你的'T = TypeVar(“T”,BaseClass,ChildClass)'工作。 – quamrana

+0

@quamrana但这意味着'myFun'的位置至少有一个这样的孩子类的理解。 - 最重要的是,它似乎完全是任意的,为什么要引用“ChildClass”:为什么不引用“SecondChildClass”或其他东西? – paul23

您应该使用具有上限的typevars:do T = TypeVar('T', bound=BaseClass)而不是T = TypeVar('T', BaseClass)

详情:

  • 当你这样做T = TypeVar('T', ClassA, ClassB, ClassC...),你要创建一个type variable with a value restriction。也就是说,你坚持认为T必须是你列出的类中的一个。

    这就是为什么不允许T = TypeVar('T', ClassA):typevar只能等于一个类,所以你不妨直接使用ClassA类型。

  • 当您执行类似T = TypeVar('T', bound=ClassA)的操作时,您将创建一个type variable with an upper bound。您坚持要求T必须是ClassA或其任何子类。