动态检查mypy中的元组长度

Dynamically checking tuple length in mypy

我有一个程序使用不同长度的元组类型的联合,它会动态检查元组的长度以优化类型。 Mypy 无法识别在这种动态检查后更准确地知道变量的类型,因此它会报告虚假类型错误。如何以 mypy 理解的方式动态检查元组长度?

在下面的示例中,当 shape 用作两个值的元组时,mypy 报告错误,即使上一行的断言确保其类型为 Tuple[int, int].

from typing import *

def f(dimensions: int,
      shape: Union[Tuple[int, int], Tuple[int, int, int]]):
    if dimensions == 2:
        assert len(shape) == 2
        height, width = shape
        print(height * width)

Mypy 在元组解包行报告错误:error: Too many values to unpack (2 expected, 3 provided)

我正在使用 mypy 0.720 和 Python 3.7.4。

我假设如果您将维度作为 2 传递,但传递包含 3 个整数的元组,则会发生这种情况。是这样吗?

很确定你可以使用:

dimensions = len(shape) 

在函数的顶部获取传递的元组中的实际条目数,而不是需要传递(可能错误的)维度参数。

这似乎是一个普遍的 python 问题,与 mypy 没有任何关系,但我很可能是错的并且错过了一些重要的事情:)

另外,如果你想在你的函数中支持任意长度的元组,我相信你可以使用 Tuple[int, ...] 类型来支持任何整数的元组,而不是使用联合如果你愿意的话。

您应该使用明确的 cast (see also this issue courtesy @aaron's 评论):

if dimensions == 2:
    assert len(shape) == 2
    shape = cast(Tuple[int, int], shape)
    height, width = shape
    print(height * width)

此外,正如其他答案所指出的,dimension 论点是多余的,您可以这样做

def f2(shape: Union[Tuple[int, int], Tuple[int, int, int]]):
    dimensions: int = len(shape)
    if dimensions == 2:
        shape = cast(Tuple[int, int], shape)
        height, width = shape
        print(height * width)