*args 和 **kwargs 的类型注释 [英] Type annotations for *args and **kwargs

查看:42
本文介绍了*args 和 **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 ints? 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆