我正在用抽象基类尝试Python的类型注释来编写一些接口。有没有办法注释*args
和**kwargs
的可能类型?
例如,如何表示函数的合理参数是一个int
或两个int
stype(args)
给出了Tuple
,所以我猜应该将该类型注释为Union[Tuple[int,int],Tuple[int]]
,但这不起作用。
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的错误消息:
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
。开箱后的添加也给出了一个我看不懂的打字错误。
如何注释*args
和**kwargs
的合理类型?
作为对前面答案的简短补充,如果您试图在Python 2文件上使用mypy,并且需要使用注释来添加类型而不是注释,则需要分别为args
和kwargs
的类型加上*
和**
前缀:
def foo(param, *args, **kwargs):
# type: (bool, *str, **int) -> None
pass
这被mypy视为与下面相同,Python 3.5版本的foo
:
def foo(param: bool, *args: str, **kwargs: int) -> None:
pass
正确的方法是使用@重载
from typing import overload
@overload
def foo(arg1: int, arg2: int) -> int:
...
@overload
def foo(arg: int) -> int:
...
def foo(*args):
try:
i, j = args
return i + j
except ValueError:
assert len(args) == 1
i = args[0]
return i
print(foo(1))
print(foo(1, 2))
请注意,您没有向实际实现中添加@重载
或类型注释,这些注释必须在最后。
您需要一个新版本的键入
和mypy来获得对存根文件之外@重载的支持。
您还可以使用它来改变返回的结果,从而明确哪些参数类型对应于哪个返回类型。例如。:
from typing import Tuple, overload
@overload
def foo(arg1: int, arg2: int) -> Tuple[int, int]:
...
@overload
def foo(arg: int) -> int:
...
def foo(*args):
try:
i, j = args
return j, i
except ValueError:
assert len(args) == 1
i = args[0]
return i
print(foo(1))
print(foo(1, 2))
对于可变位置参数(*args
)和可变关键字参数(**kw
),您只需要指定一个此类参数的预期值。
从类型提示PEP的任意参数列表和默认参数值部分:
任意参数列表也可以进行类型注释,以便定义:
def foo(*args: str, **kwds: int): ...
是可接受的,这意味着,例如,以下所有内容都表示具有有效参数类型的函数调用:
foo('a', 'b', 'c')
foo(x=1, y=2)
foo('', z=0)
因此,您应该像这样指定您的方法:
def foo(*args: int):
但是,如果你的函数只能接受一个或两个整数值,你不应该使用*args
,使用一个显式的位置参数和第二个关键字参数:
def foo(first: int, second: Optional[int] = None):
现在,函数实际上被限制为一个或两个参数,如果指定,这两个参数都必须是整数*args
始终表示0或更多,并且不能被类型提示限制为更具体的范围。
问题内容: 我正在尝试使用具有抽象基类的Python类型注释来编写一些接口。有没有一种方法来注释可能的类型和? 例如,如何表达一个函数的明智参数是一个或两个?给出,所以我的猜测是将类型注释为,但这是行不通的。 来自mypy的错误消息: Mypy不喜欢此函数调用是有道理的,因为它希望调用本身中包含a。解压后的附加内容还会产生我不理解的输入错误。 一个人如何诠释明智的类型和? 问题答案: 对于可变位置
用*args和**kwargs只是为了方便并没有强制使用它们. 当你不确定你的函数里将要传递多少参数时你可以用*args.例如,它可以传递任意数量的参数: >>> def print_everything(*args): for count, thing in enumerate(args): ... print '{0}. {1}'.format(count, thing) ..
问题内容: 在 Python的2.x的 (我用2.7),这是使用默认参数用正确的方式和? 我已经找到了与此主题相关的SO问题,但这是针对 Python 3的 : 使用 args,* kwargs和可选的/默认参数调用Python函数 在那里,他们说此方法有效: 在2.7中,结果为。有没有推荐的方法来定义这种功能? 我以这种方式工作,但我猜有更好的解决方案。 问题答案: 只需将默认参数放在: 现在,
问题内容: Python-使用args和*kwargs[副本] 问题答案: 1650 语法为和。名称和仅是约定,但没有使用它们的硬性要求。 你会使用,当你确定不是多少个参数可能会被传递给你的函数,也就是说,它允许你传递的参数任意数量给你的函数。例如: 同样,允许你处理尚未预先定义的命名参数: 你也可以将它们与命名参数一起使用。显式参数首先获取值,然后将其他所有值传递给argsand *kwargs
问题内容: 究竟什么和意味着什么? 根据Python文档,从表面上看,它传入了一个参数元组。 打印输出: 您如何有效地使用它们? 问题答案: 将和或作为函数定义的参数列表的最后一项放置,可使该函数接受任意数量的参数和/或关键字参数。 例如,如果你想编写一个返回所有参数总和的函数,则无论你提供多少,都可以这样编写: 当你覆盖某个函数并希望使用用户传入的任何参数调用原始函数时,它可能更常用于面向对象的
*args 和 **kwargs 都允许将可变数量的参数传递给函数。当不确定要在函数中传递的参数数量时,将使用它们。 *args 允许你将可变数量的参数传递给函数。 def addNumbers(*numbers): sum = 0 for number in numbers: sum = sum + number print("Sum: "