如何(在Python中,比如MyPy)输入一个需要两个参数的函数--一个枚举和一个值/成员?

from enum import Enum
from typing import TypeVar, Type

class MyEnumA(Enum):
   A = 1
   B = 2

class MyEnumB(Enum):
   A = 1
   B = 2

TE = TypeVar('TE', bound=Enum)
def myfunction(member: TE, e: Type[TE]) -> None:
    pass

myfunction(MyEnumA.A, MyEnumA) # all right
myfunction(MyEnumA.A, MyEnumB) # I expect mypy-error here but it passed

print(type(MyEnumA.A)) # says: <enum 'MyEnumA'>
print(type(MyEnumB.A)) # says: <enum 'MyEnumB'>

print(f'{isinstance(MyEnumA.A, MyEnumA)=}') # says: isinstance(MyEnumA.A, MyEnumA)=True
print(f'{isinstance(MyEnumA.A, MyEnumB)=}') # says: isinstance(MyEnumA.A, MyEnumB)=False

reveal_type(MyEnumA) # mypy: Revealed type is "def (value: builtins.object) -> e.MyEnumA"
reveal_type(MyEnumA.A) # mypy: Revealed type is "Literal[e.MyEnumA.A]?"

我想了解一下

  • 为什么MyPy没有为第二次调用说明错误;以及
  • 如何键入myfunction以便MyPy检测到其中的错误.

更多示例:

myfunction(MyEnumA.A, MyEnumA) # should pass - member of enum
myfunction(MyEnumB.A, MyEnumB) # should pass - member of enum
myfunction(MyEnumA.A, MyEnumB) # should fail - member of other enum
myfunction(MyEnumB.A, MyEnumA) # should fail - member of other enum

推荐答案

关键的观察是MyPy实际上认为MyEnumA是什么类:

reveal_type(MyEnumA) # mypy: Revealed type is "def (value: builtins.object) -> e.MyEnumA"

它给出了用以下方式注释myfunction的线索,无论它有多不明显:

P = ParamSpec('P')
def myfunction(member: TE, e: Callable[P, TE]) -> None:

这使得MyPy在第二次调用myfunction时发现输入错误:

error: Argument 2 to "myfunction" has incompatible type "Type[MyEnumA]"; expected "Callable[[object], MyEnumB]"  [arg-type]

Python相关问答推荐

在Python中管理多个OpenGVBO和VAO实例

使用matplotlib pcolormesh,如何停止从一行绘制的磁贴连接到上下行?

如何从FDaGrid实例中删除某些函数?

Polars LazyFrame在收集后未返回指定的模式顺序

不理解Value错误:在Python中使用迭代对象设置时必须具有相等的len键和值

大小为M的第N位_计数(或人口计数)的公式

如何在表中添加重复的列?

如何在Python中找到线性依赖mod 2

调用decorator返回原始函数的输出

使用Python从URL下载Excel文件

名为__main__. py的Python模块在导入时不运行'

在嵌套span下的span中擦除信息

将标签移动到matplotlib饼图中楔形块的开始处

Python—压缩叶 map html作为邮箱附件并通过sendgrid发送

Flask运行时无法在Python中打印到控制台

如何使用正则表达式修改toml文件中指定字段中的参数值

使用Python异步地持久跟踪用户输入

mdates定位器在图表中显示不存在的时间间隔

如何强制向量中的特定元素在Gekko中处于优化解决方案中

为什么Visual Studio Code说我的代码在使用Pandas concat函数后无法访问?