mypy 是自相矛盾还是只是我? Mypy 在变量上给出错误,但在完全相同的文字上却没有给出错误

问题描述 投票:0回答:1

以下代码:

def foo(bar: dict[int | float, int | float]) -> None:
    pass

foo({1: 1})
bas = {1: 1}
foo(bas)

触发以下 mypy 错误:

6: error: Argument 1 to "foo" has incompatible type "dict[int, int]"; expected "dict[int | float, int | float]"  [arg-type] 

我在函数

Table.replace_schema_metadata
中使用 pyarrow 遇到了这个错误。

  1. 错误出现在第 6 行而不是第 4 行:即使用文字就可以了, 但与变量的值不同。为什么?

  2. 为什么

    dict[int, int]
    dict[int | float, int | float]
    不兼容?

  3. 我可以做什么来解决这个错误(除了

    # type: ignore[arg-type]
    )?

使用Python 3.11.3和mypy 1.9.0。

python mypy python-typing
1个回答
0
投票

这里需要理解的重要一点是 MyPy 如何进行类型推断。由于您没有指定函数签名以外的变量类型,因此 MyPy 必须“猜测”其他变量的类型。 MyPy 文档

中甚至描述了这种确切的情况

声明的参数类型也用于类型上下文。在此程序中,mypy 知道空列表

[]
应该具有类型
list[int]
,基于
arg
中声明的
foo
类型:

def foo(arg: list[int]) -> None:
    print('Items:', ''.join(str(a) for a in arg))

foo([])  # OK

最相关的部分:

但是,上下文仅适用于单个语句。这里 mypy 需要对空列表进行注释,因为上下文仅在以下语句中可用:

def foo(arg: list[int]) -> None:
    print('Items:', ', '.join(arg))

a = []  # Error: Need type annotation for "a"
foo(a)

解决方案 - 为变量添加类型注释:

a: list[int] = []  # OK
foo(a)

或者,就您而言:

bas: dict[int|float, int|float] = {1: 1}

如果你想避免每次都使用冗长的类型,你可以创建一个别名:

type numberDict = dict[int|float, int|float]

def foo(bar: numberDict) -> None:
    pass

foo({1: 1})
bas: numberDict = {1: 1}
foo(bas)
© www.soinside.com 2019 - 2024. All rights reserved.