使用Enum Flag时mypy报类型不兼容警告:是否为误报?如何实现子集枚举变量?
问题
我希望创建一个可取自某枚举值集合的变量,之后在其他场景中从中选取特定枚举值使用。编写了如下代码:
from enum import Flag, auto class MyEnum(Flag): FOO: int = auto() BAR: int = auto() MOO: int = auto() def use_enum(my_enum: MyEnum) -> None: print(my_enum) if __name__ == "__main__": any_enum: MyEnum = MyEnum.FOO | MyEnum.BAR print(type(any_enum.FOO)) use_enum(my_enum=any_enum.FOO) # Argument "my_enum" to "use_enum" has incompatible type "int"; expected "MyEnum" [arg-type]mypy(error)
运行代码后输出结果正常:
<enum 'MyEnum'> MyEnum.FOO
但mypy提示类型不兼容错误,请问这是否属于mypy的误报?有没有其他实现方式,能让any_enum表示MyEnum的子集?
解答
这不算mypy的误报。当你通过any_enum.FOO访问枚举成员时,Python的Flag枚举在实例上访问类属性时,会返回该成员对应的整数值(因为Flag的实例是整数的封装),而非MyEnum类型的实例——虽然运行时打印出来看起来像枚举,但实际类型是int,这和mypy的类型检查结果一致。
要让any_enum表示MyEnum的子集,同时能正确获取枚举成员类型,有两种可行方式:
直接使用类成员而非实例属性:
如果只是想复用枚举子集,不需要通过实例访问,直接用类本身或者定义子集变量为枚举成员的集合:if __name__ == "__main__": enum_subset = {MyEnum.FOO, MyEnum.BAR} use_enum(my_enum=MyEnum.FOO) # 类型正常自定义枚举方法获取成员:
在MyEnum中添加方法,从实例的位掩码中提取对应的枚举成员,确保返回类型是MyEnum:from enum import Flag, auto from typing import Optional class MyEnum(Flag): FOO: int = auto() BAR: int = auto() MOO: int = auto() def get_member(self, member: 'MyEnum') -> Optional['MyEnum']: if self & member: return member return None def use_enum(my_enum: MyEnum) -> None: print(my_enum) if __name__ == "__main__": any_enum: MyEnum = MyEnum.FOO | MyEnum.BAR foo_member = any_enum.get_member(MyEnum.FOO) if foo_member: use_enum(my_enum=foo_member) # mypy不再报错
内容的提问来源于stack exchange,提问作者PepsiBandit
相关产品推荐
相关产品推荐

