【问题标题】:Dynamically checking tuple length in mypy在 mypy 中动态检查元组长度
【发布时间】:2020-04-13 03:06:22
【问题描述】:

我的程序使用不同长度的元组类型的联合,它动态检查元组的长度以优化类型。 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 一起使用。

【问题讨论】:

  • 为什么将dimensions 作为单独的参数传递,而不是直接使用len(shape)
  • 我认为这个建议会提供更好的python代码,但我认为它不会解决mypy问题。
  • 无直接支持:python/mypy#1178,建议使用cast 作为解决方法。
  • @Code-Apprentice 该示例是从一个较大的程序中简化而来的,其中dimensionsshape 存在于不同的数据结构中,因为其他代码需要它们。

标签: python tuples mypy


【解决方案1】:

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

很确定你可以使用:

dimensions = len(shape) 

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

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

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

【讨论】:

  • 我认为这个建议会提供更好的python代码,但我不认为它会解决mypy问题。
  • @Dave_Birch 这个例子是从一个更大的程序中缩减而来的,而变量dimensionshape在原程序中由于其他原因已经存在。它们不直接作为函数参数传递。
【解决方案2】:

您应该使用明确的cast(另请参阅this issue 礼貌@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)         

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多