动态创建Enum时如何注解test_func2以通过mypy检查
解决动态枚举的mypy类型检查问题
问题场景
以下代码运行正常,但执行mypy x.py时会触发类型检查错误:
from __future__ import annotations from enum import Enum, auto from typing import Type class AEnum(Enum): VALUE1 = auto() VALUE2 = auto() SPS_STATES = { "pre": "PreReleased", "rel": "Released", "ret": "Retired", "tgt": "Target" } SpsState = Enum('SpsState', list(SPS_STATES.values())) def test_func() -> AEnum: return AEnum.VALUE1 def test_func2() -> Type[Enum]: return SpsState.Released print(f'{test_func()}, {type(test_func())}, {[state.name for state in AEnum]}') print(f'{test_func2()}, {type(test_func2())}, {[state.name for state in SpsState]}')
运行输出(符合预期)
AEnum.VALUE1, <enum 'AEnum'>, ['VALUE1', 'VALUE2'] SpsState.Released, <enum 'SpsState'>, ['PreReleased', 'Released', 'Retired', 'Target']
mypy错误信息
x.py:18: error: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members [misc] x.py:25: error: "type[SpsState]" has no attribute "Released" [attr-defined] Found 2 errors in 1 file (checked 1 source file)
需求:修正test_func2的类型注解,让mypy检查通过,且代码能自适应SPS_STATES字典的变更(不硬编码枚举值)。
错误原因
- 动态枚举无法被静态分析:
SpsState通过list(SPS_STATES.values())动态生成,mypy无法静态推断枚举成员,因此提示参数类型错误,且识别不到SpsState.Released这个成员。 - 返回类型注解错误:
test_func2返回的是枚举实例(SpsState.Released),但原注解Type[Enum]表示返回枚举类的类型,两者不匹配。
解决方案
修改后的完整代码
from __future__ import annotations from enum import Enum, auto from typing import cast class AEnum(Enum): VALUE1 = auto() VALUE2 = auto() SPS_STATES = { "pre": "PreReleased", "rel": "Released", "ret": "Retired", "tgt": "Target" } # 忽略mypy对动态枚举参数的检查,适配外部字典的动态变更 SpsState = Enum('SpsState', list(SPS_STATES.values())) # type: ignore[misc] def test_func() -> AEnum: return AEnum.VALUE1 def test_func2() -> SpsState: # 用getattr动态获取枚举成员,cast断言类型让mypy认可 return cast(SpsState, getattr(SpsState, "Released")) print(f'{test_func()}, {type(test_func())}, {[state.name for state in AEnum]}') print(f'{test_func2()}, {type(test_func2())}, {[state.name for state in SpsState]}')
关键修改点
- 修正返回类型:将
test_func2的返回注解改为SpsState,匹配实际返回的枚举实例类型。 - 动态获取枚举成员:用
getattr(SpsState, "Released")替代直接访问SpsState.Released,避免mypy因无法识别动态成员而报错。 - 类型断言:用
cast(SpsState, ...)告诉mypy获取到的对象是SpsState类型的实例。 - 忽略动态枚举参数检查:给
SpsState的定义添加# type: ignore[misc],因为我们需要自适应动态字典的场景,无法使用字面量参数。
验证
执行mypy x.py后,不再出现类型检查错误,同时代码依然能根据SPS_STATES的变更自动更新枚举成员。
内容的提问来源于stack exchange,提问作者user2606240
相关产品推荐
相关产品推荐

