5

我有一个返回 2 元组但可选的 3 元组的函数。我如何用类型注释来描述这个?

例如:

from typing import Tuple

def example(i):
    # type: (int) -> Tuple[int, int, <what to put here?>]
    if i < 10:
       return (i, i+1, 1)
    else:
       return (i, i+1)

我可以像下面这样使用 Union,但它看起来很乱。

# type: (int) -> Union[Tuple[int, int], Tuple[int, int, int]]
4

1 回答 1

8

正如评论中所指出的,工会可能是更好的方法。如果签名看起来很乱,你可以像这样使用类型别名

from typing import Tuple, Union

MyType = Union[Tuple[int, int], Tuple[int, int, int]]

def example1(i):
    # type: (int) -> MyType
    ...snip...

另一种方法是使用“不定长度”元组类型。您基本上会放弃对元组的确切长度进行编码,但作为交换可以规范化返回类型并避免该联合。(如果您的代码确实依赖于长度,这可能不是最好的方法)。

def example2(i):
    # type: (int) -> Tuple[int, ...]
    ...snip...

但是,一种更激进的方法是考虑重组代码以避免这种情况。

毕竟,如果您要返回这两种不同的类型,那么函数的调用者可能无论如何都需要检查长度,对吧?

在这种情况下,一个想法是放弃返回元组,而是返回NamedTuple或自定义类,两者都有一个可选字段。然后,您可以将“长度”检查转换为“此字段是否设置为无”检查。

我想,从某种意义上说,NamedTuple 方法也可以在某种程度上满足您的原始请求,只要您不介意转换元组/增加的开销。

from typing import NamedTuple, Optional

MyType2 = NamedTuple('MyType2', (
    ('x', int),
    ('y', int),
    ('z', Optional[int]),
))

class MyType3(object):
    def __init__(self, x, y, z):
        # type: (int, int, Optional[int]) -> None
        self.x = x
        self.y = y
        self.z = z

(一旦PEP 557被接受并集成到语言中,“自定义类”方法可能会更加优雅)。

如果您提前知道您期望哪种元组,另一种方法是将您的函数分成两部分。然后,您可以调用适当类型的函数。

于 2017-09-22T18:25:02.867 回答