Python mypy检查TypeVar(bound=Union[A, B])的返回类型不会出错,而TypeVar(A, B)会出错。

我被卡住了,试图理解 TypeVar 当以两种不同的方式使用它时。

  • Enums = TypeVar("Enums", Enum1, Enum2)
  • Enums = TypeVar("Enums", bound=Union[Enum1, Enum2])

以下是我使用的代码

#!/usr/bin/env python3.6

"""Figuring out why enum is saying incompatible return type."""


from enum import IntEnum, EnumMeta
from typing import TypeVar, Union


class Enum1(IntEnum):

    MEMBER1 = 1
    MEMBER2 = 2


class Enum2(IntEnum):

    MEMBER3 = 3
    MEMBER4 = 4


# Enums = TypeVar("Enums", bound=Union[Enum1, Enum2])  # Case 1... Success
Enums = TypeVar("Enums", Enum1, Enum2)  # Case 2... error: Incompatible return value


def _enum_to_num(val: int, cast_enum: EnumMeta) -> Enums:
    return cast_enum(val)


def get_some_enum(val: int) -> Enum1:
    return _enum_to_num(val, Enum1)


def get_another_enum(val: int) -> Enum2:
    return _enum_to_num(val, Enum2)  # line 35

当运行 mypy==0.770:

  • Case 1 Success: no issues found
  • Case 2: 35: error: Incompatible return value type (got "Enum1", expected "Enum2")

:: 此案是 与本题类似。TypeVar(‘T’, A, B)和TypeVar(‘T’, bound=Union[A, B])之间的区别。

答案解释当使用案例1(bound=Union[Enum1, Enum2]),以下是合法的。

  1. Union[Enum1, Enum2]
  2. Enum1
  3. Enum2

而当使用案例2时A, B),下面的内容是合法的。

  1. Enum1
  2. Enum2

但是,我不认为这个答案能解释我的问题,我没有使用… … Union 的情况。

谁能告诉我这是怎么回事?

解决方案:

我认为错误的发生是因为类型检查器没有足够的信息来检查 推断 通过查看输入参数的类型来确定返回类型。虽然处理方式可能会有所改进。

假设你有一个简单的通用函数。

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_enumEnumMeta,类型检查器无法判断是否 cast_enum 将返回 Enums 或不。看来它只是假设会返回 Enum1的错误,并导致 _enum_to_num(val, Enum2).

你知道的 _enum_to_num(val, Enum2) 将返回 Enum2 因为你知道 价值cast_enumEnum2. 该 价值 是什么 类型 检查器一般不碰。这可能会让人感到困惑。价值 变化的 cast_enumEnum2类型cast_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打赏
共{{data.count}}人
人已打赏
未分类

如何在DataElement中控制SegmentedControl的外观?

2022-9-8 4:02:17

未分类

如何用一个ruby作业和一个python worker来使用Faktory?

2022-9-8 4:02:19

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索