我有一个函数,它接受五个整数的列表或五个整数作为元组(*argv)。
这是我的函数标题:
def __init__(self, *argv: Union[int, list]) -> None:
稍后在此函数中,我检查该元组的内容,看看它是一个列表还是五个单独的整数。
if type(argv[0]) == int:
self._l1 = [argv[0], argv[1], argv[2], argv[3], argv[4]]
else:
self._l1 = argv[0]
此时代码中 l1 是一个列表。 self._l1 绝对是一个列表,它不再是一个 int,它是一个列表。
但是稍后在我的代码中运行此行时:
self._myvar = self._l1.count(1)
我从 MyPy 返回此错误
赋值中的类型不兼容(表达式的类型为“Union[int, List[Any]]”,变量的类型为“List[Union[int, List[Any]]]”)
我是否输入错误,我需要输入什么?我尝试了很多不同的类型,但不断出错。
据我所知,我的输入是一个元组,其中包含一个整数列表或五个整数。我假设它类似于 Union[Tuple[List[int]], Tuple[int, ...]] 或只是 Union[List[int], int] 或 Union[List[int], Tuple[int, . ..]],或类似的东西,但这些都不适合我。
我建议确保
_li
始终为 List[int]
类型。
我还没有测试下面的代码,但是
cast
应该可以工作:
if isinstance(argv[0], int):
self._l1 = [cast(int, argv[0]), cast(int, argv[1]), cast(int, argv[2]), cast(int, argv[3]), cast(int, argv[4])]
else:
self._l1 = cast(List[int], argv[0])
print(type(self._li))
以及声明 _li 和 _myvar 的位置:
_li: List[int]
_myvar: List[int]
为什么不使用
typing.overload
?
它看起来像这样:
from __future__ import annotations
from typing import overload
class MyClass:
@overload
def __init__(self: MyClass, a: int, b: int, c: int, d: int, e: int) -> None:
...
@overload
def __init__(self: MyClass, abcde: tuple[int,int,int,int,int]) -> None:
...
def __init__(self, a, *bcde):
if bcde:
b, c, d, e = *bcde
# etc
else:
a, b, c, d, e = *a
# etc
因此,您将
argv
定义为带有 *
的序列,其中可以包含 int 值或 int 值列表。所以你真正想做的是“展平”序列。
def flatten(alist):
"""Flatten a nested set of lists into one list."""
rv = []
for val in alist:
if isinstance(val, (list, tuple)):
rv.extend(flatten(val))
else:
rv.append(val)
return rv
class MyClass:
def __init__(self, *argv: Union[int, list]):
# argv is now a tuple of Union[int, list], or List[Union[int, List]], as the compiler says.
self._l1 = flatten(argv)
# Now, you want to verify they are all ints, and that there are five.
if len(self._l1) != 5:
raise ValueError("Need five ints")
if not all(isinstance(o, int) for o in self._l1):
raise ValueError("not sequence of ints")
# Now you have a single list of 5 ints.