我正在试用Python的类型注释和抽象基类来编写一些接口.有没有办法注释*args**kwargs这两种可能的类型?

例如,如何表示函数的合理参数是int还是两个inttype(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注释合理的类型?

推荐答案

对于变量位置参数(*args)和变量关键字参数(**kw),您只需要为one个这样的参数指定期望值.

Type Hints个PEP中的Arbitrary argument lists and default argument values section个开始:

还可以对任意参数列表进行类型注释,以便定义:

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 always表示0或更多,不能被类型提示限制在更具体的范围内.

Python相关问答推荐

拆分pandas列并创建包含这些拆分值计数的新列

使用GEKKO在简单DTE系统中进行一致初始化

优化在numpy数组中非零值周围创建缓冲区的函数的性能

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

当使用keras.utils.Image_dataset_from_directory仅加载测试数据集时,结果不同

无法定位元素错误404

Python+线程\TrocessPoolExecutor

在嵌套span下的span中擦除信息

* 动态地 * 修饰Python中的递归函数

python中csv. Dictreader. fieldname的类型是什么?'

基于多个数组的多个条件将值添加到numpy数组

如何在Python 3.9.6和MacOS Sonoma 14.3.1下安装Pyregion

Python—在嵌套列表中添加相同索引的元素,然后计算平均值

如何在Django模板中显示串行化器错误

在round函数中使用列值

在pandas中,如何在由两列加上一个值列组成的枢轴期间或之后可靠地设置多级列的索引顺序,

随机森林n_估计器的计算

将像素信息写入文件并读取该文件

FileNotFoundError:[WinError 2]系统找不到指定的文件:在os.listdir中查找扩展名

是否将Pandas 数据帧标题/标题以纯文本格式转换为字符串输出?