2017-09-14 217 views
2

嗯,我正在考慮一個案例,我有一個(幾個)孩子的基類。我有一個函數,它接受一個基類對象列表,並返回一個新列表,其中包含這些對象。蟒蛇類型提示,返回相同類型的輸入

現在,如果我會用一個子類明顯的回報是這些子類對象的列表:考慮以下簡單的情況:

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

回答

1

您應該使用具有上限的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或其任何子類。