Python类型提示:联合[int,列表[int]]-不支持索引赋值的目标
Python类型提示:联合[int,列表[int]]-不支持索引赋值的目标,python,list,union,type-hinting,mypy,Python,List,Union,Type Hinting,Mypy,myunionA可以是整数或整数列表。 我如何写打字提示来反映这一点 它尝试了以下代码,并使用mypy对其进行了测试。最后一行失败-请参阅错误文本 numbers: List[int] myunionA: Union[int, List[int]] myunionB: Union[int, List[int]] numbers = [11, 22] numbers[2] = 3 myunionA = 2 myunionB[2] = 22 # ERROR(mypy): Unsupported
myunionA
可以是整数或整数列表。
我如何写打字提示来反映这一点
它尝试了以下代码,并使用mypy对其进行了测试。最后一行失败-请参阅错误文本
numbers: List[int]
myunionA: Union[int, List[int]]
myunionB: Union[int, List[int]]
numbers = [11, 22]
numbers[2] = 3
myunionA = 2
myunionB[2] = 22 # ERROR(mypy): Unsupported target for indexed assignment
如何编写一个typehint,让我分配一个整数或一组整数?正如deceze在评论中所说,您的代码确实不可靠。如果有人做下面的事情呢
# Legal, since myunionB can be *either* int or List[int]
myunionB: Union[int, List[int]] = 99
# Boom! At runtime, we get a "int is not subscriptable" error
myunionB[2] = 22
如果您想让mypy了解您的联合当前恰好是一个列表,那么您需要缩小执行isinstance检查等的变量的类型
if isinstance(myunionB, list):
# Type of myunionB is understood to be just List[int] here,
# so this type-checks
myunionB[2] = 22
else:
# And myunionB is understood to be just int here
myunionB = 100
# Alternatively, you can use an assert
assert isinstance(myunionB, list)
myunionB[2] = 22
或者更好的方法是,重新设计代码,这样您就不需要从联合开始,只需要将其作为一个列表[int]
。在大多数情况下,尽量减少联合类型的使用是一个好主意——经常这样做(虽然不总是这样!)最终会使代码更简单、更容易理解。类型注释在运行时没有效果。仅仅因为您指出了myUnionB
应该是int
或int
列表,所以您从未将其实际定义为列表,更不用说包含至少3个元素的列表,以便您可以将其分配给myUnionB[2]
错误信息可能更清晰
myunionB
是不受支持的目标,因为该名称尚不存在。变量注释不会“创建”变量,因为它不会为被注释的名称分配任何值(即使是隐式的None
)。您不能安全地分配到Union[int,List[int]]
的索引,因为您不知道它是int
还是List[int]
,而操作将在其中一个上失败。类型提示是正确的,错误也是正确的。您需要编写额外的代码来缩小它在运行时是哪种类型的可能性。(我不知道如何以一种让mypy特别满意的方式做到这一点,因为我没有这方面的经验。)