Python 3.8自定义Enum基类结合auto()的失效问题排查
解决Python 3.8中自定义
__new__后Enum auto()失效的问题 在Python 3.8中,当Enum子类自定义__new__方法时,auto()无法被自动解析为预期的小写枚举名称,而是保留为<enum.auto object>。这是因为默认Enum的__new__逻辑中处理auto()的代码被自定义实现覆盖了,需要手动在__new__中补充auto()的解析逻辑。
解决方案代码示例
首先是你的LowercaseEnum基类:
from enum import Enum, auto class LowercaseEnum(str, Enum): def _generate_next_value_(name, start, count, last_values): # 让auto()生成枚举名称的小写形式 return name.lower() def __new__(cls, value): # 基类逻辑:将值转为小写 obj = str.__new__(cls, value.lower()) obj._value_ = value.lower() return obj
正常工作的子类(无自定义__new__)
class Test(LowercaseEnum): FIRST = auto() SECOND = auto() # 测试结果:Test.FIRST.value → 'first',符合预期
修复前有问题的子类(自定义__new__)
class Test2(LowercaseEnum): FIRST = auto() SECOND = auto() def __new__(cls, value, index=None): obj = str.__new__(cls, value) obj._value_ = value obj.index = index return obj # 问题表现:Test2.FIRST.value → <enum.auto object>,而非预期的'first'
修复后的子类(添加auto()处理逻辑)
class Test2Fixed(LowercaseEnum): FIRST = auto() SECOND = auto() def __new__(cls, value, index=None): # 第一步:手动解析auto()实例 if isinstance(value, auto): # 获取当前要创建的枚举成员名称 member_names = list(cls.__members__.keys()) current_name = member_names[len(member_names)] # 调用基类的_generate_next_value_生成小写名称 value = cls._generate_next_value_( current_name, start=1, count=len(member_names)+1, last_values=[m.value for m in cls.__members__.values()] ) # 第二步:遵循基类逻辑,将值转为小写 value = value.lower() # 第三步:创建实例并设置自定义属性 obj = str.__new__(cls, value) obj._value_ = value obj.index = index if index is not None else len(cls.__members__) return obj # 测试结果:Test2Fixed.FIRST.value → 'first',index属性正常工作
关键逻辑说明
- 检测并解析
auto():在自定义__new__开头判断传入的value是否为auto实例,若是则调用基类的_generate_next_value_生成对应的小写成员名称。 - 对齐基类逻辑:对解析后的值执行小写转换,确保和基类行为一致。
- 完成实例初始化:创建字符串实例并设置自定义属性,保持原有功能。
内容的提问来源于stack exchange,提问作者Mad Physicist
相关产品推荐
相关产品推荐

