*args 和 **kwargs 的类型注释 [英] Type annotations for *args and **kwargs
问题描述
我正在尝试使用抽象基类的 Python 类型注释来编写一些接口.有没有办法注释 *args
和 **kwargs
的可能类型?
I'm trying out Python's type annotations with abstract base classes to write some interfaces. Is there a way to annotate the possible types of *args
and **kwargs
?
例如,如何表示函数的合理参数是一个 int
或两个 int
?type(args)
给出 Tuple
所以我的猜测是将类型注释为 Union[Tuple[int, int], Tuple[int]]
,但这不起作用.
For example, how would one express that the sensible arguments to a function are either an int
or two int
s? type(args)
gives Tuple
so my guess was to annotate the type as Union[Tuple[int, int], Tuple[int]]
, but this doesn't work.
from typing import Union, Tuple
def foo(*args: Union[Tuple[int, int], Tuple[int]]):
try:
i, j = args
return i + j
except ValueError:
assert len(args) == 1
i = args[0]
return i
# ok
print(foo((1,)))
print(foo((1, 2)))
# mypy does not like this
print(foo(1))
print(foo(1, 2))
来自 mypy 的错误消息:
Error messages from mypy:
t.py: note: In function "foo":
t.py:6: error: Unsupported operand types for + ("tuple" and "Union[Tuple[int, int], Tuple[int]]")
t.py: note: At top level:
t.py:12: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:14: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:15: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:15: error: Argument 2 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
mypy 不喜欢这个函数调用是有道理的,因为它期望调用本身有一个 tuple
.解压后的添加也出现了我不明白的打字错误.
It makes sense that mypy doesn't like this for the function call because it expects there to be a tuple
in the call itself. The addition after unpacking also gives a typing error that I don't understand.
如何注释*args
和**kwargs
的合理类型?
How does one annotate the sensible types for *args
and **kwargs
?
推荐答案
对于可变位置参数 (*args
) 和可变关键字参数 (**kw
) 你只需要为一个这样的参数指定期望值.
For variable positional arguments (*args
) and variable keyword arguments (**kw
) you only need to specify the expected value for one such argument.
来自 任意参数列表和默认参数值部分类型提示 PEP:
任意参数列表也可以进行类型注释,以便定义:
Arbitrary argument lists can as well be type annotated, so that the definition:
def foo(*args: str, **kwds: int): ...
是可以接受的,这意味着,例如,以下所有表示具有有效参数类型的函数调用:
is acceptable and it means that, e.g., all of the following represent function calls with valid types of arguments:
foo('a', 'b', 'c')
foo(x=1, y=2)
foo('', z=0)
所以你想像这样指定你的方法:
So you'd want to specify your method like this:
def foo(*args: int):
但是,如果您的函数只能接受一个或两个整数值,则根本不应使用 *args
,而应使用一个显式位置参数和第二个关键字参数:
However, if your function can only accept either one or two integer values, you should not use *args
at all, use one explicit positional argument and a second keyword argument:
def foo(first: int, second: Optional[int] = None):
现在您的函数实际上仅限于一两个参数,并且如果指定,两者都必须是整数.*args
always 表示 0 或更多,并且不能被类型提示限制到更具体的范围.
Now your function is actually limited to one or two arguments, and both must be integers if specified. *args
always means 0 or more, and can't be limited by type hints to a more specific range.
这篇关于*args 和 **kwargs 的类型注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!