【问题标题】: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 时遇到这些错误。

标签: python python-3.x type-hinting mypy python-typing


【解决方案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:这是因为tuples 和lists 用于不同的目的:tuples 是异构容器(例如任意函数的位置参数或来自 RDBMS 的单个表记录,或在数学世界中——不同集合的笛卡尔积的元素(或笛卡尔积的联合),因此每个坐标可能有不同的类型,但它们的数量通常是固定的),而lists 是同质的(如集合相同的表记录或某些集合的有限元素序列)
  • @Montreal: 所以Tuple[str] 是一个单一的str 对象tuple,而List[str] 是任意数量的str 对象的集合
【解决方案2】:

除了 Azat 发布的省略号答案之外,您还可以使用 @typing.overloadtyping.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

【讨论】:

  • 我知道它,但我的元组可能很长,所以它不是一个选项。无论如何,谢谢。
  • btw overloads 应该在实施之前进行
猜你喜欢
  • 2019-11-05
  • 2018-08-01
  • 2019-05-24
  • 1970-01-01
  • 2021-04-04
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
相关资源
最近更新 更多