如何使用类型注释在 Python 中注释可变参数?

Posted

技术标签:

【中文标题】如何使用类型注释在 Python 中注释可变参数?【英文标题】:How to annotate variadic parameters in Python using typing annotations? 【发布时间】:2018-08-01 06:09:00 【问题描述】:

如何标注变参函数的参数?

例子:

def foo(*args):  # Each arg expected to be of type T
    ...

是否有任何打字注释?

【问题讨论】:

【参考方案1】:

如果每个参数都有一个TheType 类型 - 按照PEP-484 中的说明对其进行注释:

def foo(*args: TheType):
    ...

不要使用:def foo(*args: Tuple[TheType]):,因为指定 Tuple[TheType] 意味着它是一个单元素元组 - 带有一个 TheType 元素,这不是可变参数 args 的用途。

【讨论】:

好吧,指定Tuple[TheType] 实际上意味着您期望TheType 类型的元组作为变量参数。 本身 args 已经是一个同构元组,星号只是扩展它。这就是为什么您只留下注释类型【参考方案2】:

tl;博士

基本上args 被视为同质元组,kwds 被视为字典。 您只需为每个元素值注释一个类型即可。

说明

解释来自 PEP-484 的quote:

在函数foo的主体中,推导出变量args的类型为Tuple[str, ...],变量kwds的类型为Dict[str, int]

因此,无需将 args 注释为整个同质类型元组,但可以将 Tuple[T, ...] 简化为仅键入 T

关键字参数与推断为 Dict[str, T] 相同

关于元组注释中的省略号

在 python 文档中没有太多关于... aka Ellipsis 使用的信息,但是 PEP-484 确实提到了省略号在键入注释时的各种用法,例如省略某些类型注释或默认值,但最有趣的是那里是qoute 说:

元组,用于列出元素类型,例如Tuple[int, int, str]。空元组可以输入为Tuple[()]。任意长度 同质元组可以使用一种类型和省略号来表示,对于 例如Tuple[int, ...]。 (这里的... 是语法的一部分,a 字面省略号。)

因此,如果您省略星号以强制将参数作为单个元组传递,则需要保留完整的注释:

def foo(args: Tuple[T, ...]):
    ...

关于同质元组中的各种类型

由于同构元组意味着它的所有元素必须是相同的类型,那么如果您希望允许多个类型,只需使用 Union 或者甚至使用类型别名以获得更好的可读性:

MyArg = Union[int, str, bool]

def foo(*args: MyArg):
    ...

【讨论】:

你确定这是正确的方法吗?根据the pep,可变参数没有被注释为Tuple,而是像def foo(*args: str):(而不是Tuple[str])。那么,您的注释不是意味着您的函数接受可变数量的同质元组吗? 嗯……我可能错过了,因为我在寻找省略号,因为我记得有一种涉及它的方法。此外,我发现将其注释为Tuple 没有问题,并且在函数内,它确实通过了测试isinstance(args, tuple)。请注意没有* 星号。我相信*args: T*args: Tuple[T, ...] 的简写,所以我没有发现任何问题。 嗯,@Aran-Fey PyCharm 和今天的 IDEA 不能正确理解完整的语法,也不能正确识别你提到的较短版本。 @kuza 您接受了您对自己问题的回答,但问题是它不正确。 好吧,我在更新后确实纠正了自己,引用了 PEP 484。也许是 tl;dr 适合你?我会尽量缩小我的答案。

以上是关于如何使用类型注释在 Python 中注释可变参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Scala中添加另一个参数时传递可变参数?

如何注释返回类型取决于其参数的函数?

37 py为什么要使用函数函数中添加文本注释 没有返回值的函数

使用 python 3.5 样式类型注释进行鸭子打字

Kotlin自定义注释,参数

python 3.5代码中的变量需要类型注释