首页 > 解决方案 > 如何在 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从模块外部调用,我必须 import TwoInts。这似乎有点矫枉过正,这意味着我的编辑不会给我太多提示(只有我的 NamedTuple 的名称)。

当我的论点作为弱类有意义时(例如 Vector3、GenusSpecies、Address),我喜欢 NamedTuple 解决方案,但它感觉不是通用、固定长度参数(例如 TwoInts、FourteenScalars、ThreeNames)的最佳解决方案.

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

标签: pythonmypy

解决方案


我找到了!!

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!!!

推荐阅读