请考虑以下事项:
from typing import Tuple
class A(object):
def __init__(self):
pass
class B(A):
def __init__(self):
super(B, self).__init__()
def foo() -> Tuple[A]:
return tuple([B()])
foo()
PyCharm会发出警告:Expected type 'Tuple[A]', got 'Tuple[B, ...]' instead
在tuple([B()])
上。
由于B
“是一个”A
,这是恼人的和错误的。
如何最好地处理这一问题?
2条答案
按热度按时间svmlkihl1#
看看你的
return
陈述:让我们把它拆开一点。
当然,
B()
的类型是B
。[B()]
是一个列表,具有类型为B
的单个元素。此列表的静态类型被推导为list[B]
,即B
示例的列表。现在看看
tuple([B()])
,你用一个静态类型list[B]
的参数调用tuple
,如果你用一个静态类型list[B]
的参数调用tuple
,结果的静态类型是tuple[B, ...]
。它不是
tuple[A]
,甚至不是tuple[B]
。[B()]
的静态类型不包含任何长度信息,所以元组的类型也不包含任何长度信息。它只是一个包含一些B
示例的元组。问题是,你已经遍历了一个列表,你不需要这样做,直接生成一个元组:
然后,静态分析器可以直接看到,这是一个元组,其中有一个
B
类型的元素,在一个上下文中,一个tuple[A]
是预期的,并推断出该元组可以和应该被视为一个tuple[A]
。aamkag612#
如何最好地处理这一问题?
最简单的方法是返回文本声明而不是使用构造函数(语法也更简洁),如果您将
return
写为:但是,如果构造函数是从单个元素的固定长度集合初始化的,那么您也可以使用该构造函数,PyCharm编译器不会对此不满,例如:
仔细查看错误消息:
got 'Tuple[B, ...]'
个这里的省略号
...
表示您返回的是任意长度的元组(静态类型检查器会推断出这一点,因为您使用列表初始化元组),而类型提示-> Tuple[A]
需要一个固定长度的单元素元组,请参见:人教版484
Tuple[int, int, str]
。空元组的类型可以是Tuple[()]
。任意长度的同类元组可以使用一种类型和省略号来表示,例如Tuple[int, ...]
。(此处的...
是语法的一部分,即文字省略号。)我用Python 3.8和Python 3.9测试了这一点(请注意,这是
typing.Tuple
被弃用而改用参数化内置函数进行类型提示的版本)。