2 回答

TA贡献1802条经验 获得超4个赞
我认为发生错误是因为类型检查器没有足够的信息来通过查看输入参数的类型来推断返回类型。虽然处理可能会有所改善。
假设你有一个简单的泛型函数:
Enums = TypeVar("Enums", Enum1, Enum2)
def add(x: Enums, y: Enums) -> Enums:
return x
类型检查器可以通过输入参数的类型推断返回类型:
add(Enum2.MEMBER3, Enum2.MEMBER4) # ok, return Enum2
add(Enum1.MEMBER1, Enum1.MEMBER2) # ok, return Enum1
add(Enum2.MEMBER3, Enum1.MEMBER2) # not ok
再次查看您的函数_enum_to_num,类型检查器无法推断返回类型,它只是不知道将返回什么类型,因为它不知道将返回什么类型cast_enum:
def _enum_to_num(val: int, cast_enum: EnumMeta) -> Enums:
return cast_enum(val)
静态类型检查的想法是它在不执行的情况下评估代码,它调查变量的类型,而不是动态值。通过查看 的类型cast_enum,即EnumMeta,类型检查器无法判断是否cast_enum会返回Enums。看起来它只是假设它会返回Enum1,它会导致_enum_to_num(val, Enum2).
你知道它_enum_to_num(val, Enum2)会返回Enum2,因为你知道is的值。该值是类型检查器通常不会触及的东西。可能会造成混淆,变量的值是,而类型是,虽然是类型。cast_enumEnum2cast_enumEnum2cast_enumEnumMetaEnum2
这个问题可以通过告诉类型检查器类型将通过cast_enum使用来解决typing.Type:
from typing import TypeVar, Union, Type
...
def _enum_to_num(val: int, cast_enum: Type[Enums]) -> Enums:
return cast_enum(val)
错误将消失,因为现在类型检查器可以推断返回类型。

TA贡献1847条经验 获得超7个赞
我首先写一点关于 mypy 看到和报告的内容,然后提出这是否是 mypy 错误的问题。
消息:
Incompatible return value type (got "Enum1", expected "Enum2")
这里的意思是粗略地认为它的一个Enum2
或一个子类型是预期的。Enum2
是声明的返回值get_another_enum()
。但是 mypy 认为函数调用_enum_to_num()
正在返回一个Enum1
类型。
Any
“大致”部分是因为当类型未绑定、或为、或类型时,类型检查存在异常Union
;但这不适用于此示例。
Mypy 决定cast_enum()
in中的函数_enum_to_num()
返回列出的第一个Enums
类型——我想作为一个静态类型检查器,它必须选择一个,这就是它的作用。
因此,如果您在Enums
作业中切换顺序并编写:
Enums = TypeVar("Enums", Enum2, Enum1) # Case 2... error: Incompatible return value
然后第 35 行将成功,但返回get_some_enum()
将失败并显示以下消息:
error: Incompatible return value type (got "Enum2", expected "Enum1")
至于这是否是mypy的bug,很难说……
type()
使用orininstance()
函数在这里找不到动态类型错误;运行代码也按预期工作。
另一方面,无论是在编译时还是在运行时,Python 都不会检查返回类型:您可以将返回类型更改_enum_to_none()
为 beNone
并且就 Python 解释器而言仍然有效。
然后问题归结为:在 mypy 强加的静态类型系统中,这是一个错误吗?(我不认为 PEP 484、526 或其他数字试图解决这个问题)。
更有资格的人应该回答这个问题,这是否是一个应该被静态分析器捕获的错误,特别是 mypy。
请参阅 Ken Hung 的答案,以更明确地消除 mypy 的错误。
添加回答
举报