代码之家  ›  专栏  ›  技术社区  ›  Dewald Abrie

Python类型注释:将元组中的项标记为可选项

  •  5
  • Dewald Abrie  · 技术社区  · 7 年前

    我有一个函数,返回一个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]]
    
    1 回复  |  直到 7 年前
        1
  •  8
  •   Michael0x2a    7 年前

    正如评论中指出的那样,工会可能是更好的办法。如果签名看起来很凌乱,您可以使用 type aliases

    from typing import Tuple, Union
    
    MyType = Union[Tuple[int, int], Tuple[int, int, int]]
    
    def example1(i):
        # type: (int) -> MyType
        ...snip...
    

    "indefinite length" Tuple type . 您基本上会放弃对元组的确切长度进行编码,但作为交换,可以规范化返回类型并避免这种联合。(如果您的代码

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

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

    毕竟,如果返回这两种不同的类型,函数的调用方可能需要检查长度,对吗?

    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 被接受并融入语言)。

    另一种方法是,如果你提前知道你想要哪种元组,就把你的函数一分为二。然后,您可以调用适当类型的函数。

    推荐文章