如何在mypy中正确指定固定长度的序列?

时间:2018-12-20 16:53:32

标签: python mypy

当我编写一个期望使用特定长度元组的函数时,可以使用Tuple[int, int]输入参数(特定长度为2)。

from typing import Tuple


def tuple_in(a_tuple: Tuple[int, int]) -> Tuple[int, int]:
    return a_tuple


tuple_in((0, 1))  # mypy is happy

那太好了,只要我有一个元组可以通过。如果我没有元组,那么我将要做的所拥有的任何内容都强制转换为元组是很困难的。

tuple_in(tuple([0, 1]))  # Expected Tuple[int, int], got Tuple[int, ...]

tuple_in(tuple(x for x in [0, 1]))  # Expected Tuple[int, int], got Tuple[int, ...]

tuple_in(tuple(x for x in [0, 1][:2]))  # Expected Tuple[int, int], got Tuple[int, ...]

我明白了。转换不确定长度的参数会产生不确定长度的元组。但这使我的生活变得困难。

这有效,但它不能真正有效, 具有2-3个以上的值

my_list = [0, 1]
tuple_in((my_list[0], my_list[1]))  # mypy is happy. My eyes hurt.

键入模块具有cast函数,可将那些Tuple[int, ...]转换为Tuple[int, int],但这并不比type: ignore好。

tuple_in(cast(Tuple[int, int], "obviously not a tuple"))  # mypy is happy

幸运的是,键入模块提供了更好的解决方案:NamedTuple

from typing import NamedTuple

TwoInts = NamedTuple("TwoInts", [("a", int), ("b", int)])


def named_tuple_in(a_tuple: TwoInts) -> Tuple[int, int]:
    return a_tuple


named_tuple_in(Tuple2(*[0, 1]))  # mypy is happy

但是,如果要从模块外部调用tuple_in,则必须导入TwoInts。这似乎有些矫kill过正,这意味着我的编辑器不会给我太多提示(仅提供我NamedTuple的名称)。

当我的参数对于弱类(例如Vector3,GenusSpecies,Address)有意义时,我喜欢NamedTuple解决方案,但对于通用的定长参数(例如TwoInts,FourteenScalars),它似乎并不是最佳的解决方案,ThreeNames)。

键入此类固定长度参数的预期方法是什么?

1 个答案:

答案 0 :(得分:0)

我找到了!!

from typing import Tuple


def tuple_in(a_tuple: Tuple[int, int]) -> Tuple[int, int]:
    return a_tuple


tuple_in([0, 1])[:2]  # mypy is happy!!!