python 类型提示,return 与输入类型相同
python type hint, return same type as input
好吧,我正在考虑这样一种情况,我有一个 baseclass 和(几个)children。我有一个函数,它接受一个 baseclass objects 列表,return 是一个包含这些 objects 的新列表。
现在如果我要使用 child class 显然 return 是那些 child class objects 的列表:考虑以下小案例:
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(和标准类型提示)在静态代码分析期间显示错误:
"unresolved attribute reference"@idx.sum_mul_data()
现在显然这是由于 pycharm 认为函数的 return 是 "BaseClass" 类型 - 而不是 child。那我怎么说:"return same type as input"?
我尝试使用类型变量:T = TypeVar("T", BaseClass)
,尽管这给出了一个实际错误,即不能在 TypeVar
中使用单个约束。有趣的是,使用 T = TypeVar("T", BaseClass, ChildClass)
确实有效,并且 pycharm 正确地推断出 sum_div_data.
的类型(提示)
您应该使用具有上限的类型变量:使用 T = TypeVar('T', bound=BaseClass)
而不是 T = TypeVar('T', BaseClass)
。
详情:
当您执行类似 T = TypeVar('T', ClassA, ClassB, ClassC...)
的操作时,您正在创建一个 type variable with a value restriction。也就是说,您坚持 T
必须恰好是您列出的 class 之一。
这就是为什么 T = TypeVar('T', ClassA)
被禁止的原因:typevar 只能等于一个 class,所以你最好直接使用 ClassA
类型。
当您执行类似 T = TypeVar('T', bound=ClassA)
的操作时,您正在创建一个 type variable with an upper bound。您坚持认为 T
必须是 ClassA
或其任何子 class。
好吧,我正在考虑这样一种情况,我有一个 baseclass 和(几个)children。我有一个函数,它接受一个 baseclass objects 列表,return 是一个包含这些 objects 的新列表。
现在如果我要使用 child class 显然 return 是那些 child class objects 的列表:考虑以下小案例:
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(和标准类型提示)在静态代码分析期间显示错误:
"unresolved attribute reference"@idx.sum_mul_data()
现在显然这是由于 pycharm 认为函数的 return 是 "BaseClass" 类型 - 而不是 child。那我怎么说:"return same type as input"?
我尝试使用类型变量:T = TypeVar("T", BaseClass)
,尽管这给出了一个实际错误,即不能在 TypeVar
中使用单个约束。有趣的是,使用 T = TypeVar("T", BaseClass, ChildClass)
确实有效,并且 pycharm 正确地推断出 sum_div_data.
您应该使用具有上限的类型变量:使用 T = TypeVar('T', bound=BaseClass)
而不是 T = TypeVar('T', BaseClass)
。
详情:
当您执行类似
T = TypeVar('T', ClassA, ClassB, ClassC...)
的操作时,您正在创建一个 type variable with a value restriction。也就是说,您坚持T
必须恰好是您列出的 class 之一。这就是为什么
T = TypeVar('T', ClassA)
被禁止的原因:typevar 只能等于一个 class,所以你最好直接使用ClassA
类型。当您执行类似
T = TypeVar('T', bound=ClassA)
的操作时,您正在创建一个 type variable with an upper bound。您坚持认为T
必须是ClassA
或其任何子 class。