【问题标题】:Why do I get mypy no overload variant of "zip" matches argument error?为什么我得到 mypy 没有“zip”的重载变体匹配参数错误?
【发布时间】:2020-10-15 21:07:26
【问题描述】:

我有一个带有方法的类:

class TimeUtilitiesTestCase():
    def test_date_and_delta(self) -> None:
        """Tests date_and_delta utility method."""
        now = datetime.datetime.now()
        tdelta = datetime.timedelta
        int_tests = (3, 29, 86399, 86400, 86401 * 30)
        date_tests = [now - tdelta(seconds=x) for x in int_tests]
        td_tests = [tdelta(seconds=x) for x in int_tests]
        results = [(now - tdelta(seconds=x), tdelta(seconds=x)) for x in int_tests]
        for test in (int_tests, date_tests, td_tests):
            for arg, result in zip(test, results):
                dtime, delta = humanizer_portugues.time.date_and_delta(arg)
                self.assertEqualDatetime(dtime, result[0])
                self.assertEqualTimedelta(delta, result[1])
        self.assertEqual(humanizer_portugues.time.date_and_delta("NaN"), (None, "NaN"))

我正在运行严格的 mypy 检查 (configs here),但出现错误:

error: No overload variant of "zip" matches argument
types "object", "List[Tuple[datetime, timedelta]]"  [call-overload]
                for arg, result in zip(test, results):
                                   ^
note: Possible overload variants:
note:     def [_T1, _T2] zip(*iterables: Tuple[_T1, _T2]) -> Tuple[Tuple[_T
1, ...], Tuple[_T2, ...]]
note:     def [_T1, _T2, _T3] zip(*iterables: Tuple[_T1, _T2, _T3]) -> Tupl
e[Tuple[_T1, ...], Tuple[_T2, ...], Tuple[_T3, ...]]
note:     <3 more similar overloads not shown, out of 10 total overloads>

如果你想完全重现错误,你可以克隆分支strict-mypygit clone -b strict-mypy https://github.com/staticdev/humanizer-portugues.git

我尝试将 results 从列表更改为也是一个元组,但这个错误并没有消失。

我在这里打错了怎么办?


编者注:
可以使用以下最小示例重现此问题:

def bug_repr() -> None:
    ints = [1, 2]
    floats = [3.14, 2.72]
    strings = ['a', 'b']
    for numeric_list in [ints, floats]:
        for number, string in zip(numeric_list, strings):  # <-- error here
            pass

这给出了同样的错误:

main.py:6: error: No overload variant of "zip" matches argument types "object", "List[str]"
main.py:6: note: Possible overload variants:
main.py:6: note:     def [_T1, _T2] zip(*iterables: Tuple[_T1, _T2]) -> Tuple[Tuple[_T1, ...], Tuple[_T2, ...]]
main.py:6: note:     def [_T1, _T2, _T3] zip(*iterables: Tuple[_T1, _T2, _T3]) -> Tuple[Tuple[_T1, ...], Tuple[_T2, ...], Tuple[_T3, ...]]
main.py:6: note:     <3 more similar overloads not shown, out of 10 total overloads>
Found 1 error in 1 file (checked 1 source file)

您可以在 mypy Playground 上复制此内容。

【问题讨论】:

  • 如果您只是在寻找解决方法,cast(List[Union[int, float]], numeric_list) 应该可以解决问题。
  • @0x5453 你认为这是我需要强制转换的错误吗?
  • 我不是 mypy 专家,但在我未经训练的眼睛看来,它确实是个 bug。 mypy 当然可以确定intsfloats 的类型,我假设创建异构类型列表将只是Union 这些类型而不是推断object

标签: python python-3.x type-hinting mypy


【解决方案1】:

使用您的最小示例:

问题是,MyPy 推断出一个太窄的类型,即List[int]List[float],然后它无法推断List of something 的类型numeric_list。一般来说,当你放入不同的东西时,容器和静态类型安全都会出现问题。例如,你输入了一个浮点数和一个整数,那么静态分析如何知道你取出了什么?见Docs on Variance

但是你可以声明一个更通用的类型,使用Union types,来声明它可能包含多个类型。

from typing import Union, List

def bug_repr() -> None:
    ints: List[Union[int, float]] = [1, 2]
    floats: List[Union[int, float]] = [3.14, 2.72]
    strings = ['a', 'b']
    for numeric_list in [ints, floats]:
        for number, string in zip(numeric_list, strings):
            pass

或者,您可以将其声明为列表(或序列)而不指定里面的内容:

from typing import List

def bug_repr() -> None:
    ints: List = [1, 2]
    floats: List = [3.14, 2.72]
    strings = ['a', 'b']
    for numeric_list in [ints, floats]:
        for number, string in zip(numeric_list, strings):
            pass

但我不确定在内部循环中会为 number 推断出什么类型。

(注意,您也可以使用Sequence 作为更通用的类型,而不是List

【讨论】:

    猜你喜欢
    • 2020-11-27
    • 2014-02-16
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    相关资源
    最近更新 更多