如何注释采用可变长度元组的函数? (可变元组类型注释)
Posted
技术标签:
【中文标题】如何注释采用可变长度元组的函数? (可变元组类型注释)【英文标题】:How to annotate function that takes a tuple of variable length? (variadic tuple type annotation) 【发布时间】:2019-07-11 20:03:18 【问题描述】:我有一个函数,它接受一个不同长度的元组作为参数:
from typing import Tuple
def process_tuple(t: Tuple[str]):
# Do nasty tuple stuff
process_tuple(("a",))
process_tuple(("a", "b"))
process_tuple(("a", "b", "c"))
当我像上面提到的那样注释函数时,我会收到这些错误消息
fool.py:9: error: Argument 1 to "process_tuple" has incompatible type "Tuple[str, str]"; expected "Tuple[str]"
fool.py:10: error: Argument 1 to "process_tuple" has incompatible type "Tuple[str, str, str]"; expected "Tuple[str]"
process_tuple
确实适用于元组,我将它们用作可变长度的不可变列表。我在网上没有找到关于这个话题的任何共识,所以我想知道我应该如何注释这种输入。
【问题讨论】:
您在运行代码时是否遇到这些错误?我运行代码没有任何错误。 我在运行mypy
时遇到这些错误。
【参考方案1】:
我们可以像这样使用...
文字(又名Ellipsis
)来注释可变长度的同构元组:
def process_tuple(t: Tuple[str, ...]):
...
之后,错误应该会消失。
来自docs:
要指定同构类型的变长元组,请使用字面量 省略号,例如
Tuple[int, ...]
。一个普通的Tuple
相当于Tuple[Any, ...]
,然后转至tuple
。
【讨论】:
这实际上是有点反直觉和反逻辑。如果我们假设List[str]
适用于可变长度列表,那么为什么Tuple[str]
不适用于可变长度元组?而(type(("a", "a")) == type(("a", "a", "a"))
产生True
。
@Montreal:这是因为tuple
s 和list
s 用于不同的目的:tuple
s 是异构容器(例如任意函数的位置参数或来自 RDBMS 的单个表记录,或在数学世界中——不同集合的笛卡尔积的元素(或笛卡尔积的联合),因此每个坐标可能有不同的类型,但它们的数量通常是固定的),而list
s 是同质的(如集合相同的表记录或某些集合的有限元素序列)
@Montreal: 所以Tuple[str]
是一个单一的str
对象tuple
,而List[str]
是任意数量的str
对象的集合【参考方案2】:
除了 Azat 发布的省略号答案之外,您还可以使用 @typing.overload
或 typing.Union
使其更明确
from typing import Tuple
@overload
def process_tuple(t: Tuple[str]):
# Do nasty tuple stuff
@overload
def process_tuple(t: Tuple[str, str]):
...
或与联盟:
from typing import Tuple, Union
def process_tuple(t: Union[Tuple[str], Tuple[str, str], Tuple[str, str, str]]):
# Do nasty tuple stuff
【讨论】:
我知道它,但我的元组可能很长,所以它不是一个选项。无论如何,谢谢。 btwoverload
s 应该在实施之前进行以上是关于如何注释采用可变长度元组的函数? (可变元组类型注释)的主要内容,如果未能解决你的问题,请参考以下文章