如何为Enum类的所有值统一应用前缀/后缀处理?
解决方法
方案1:写个通用基类重写字符串输出
先搞一个通用的Enum基类,自动从模块名提取前缀,重写__str__和__repr__方法,之后所有Enum都继承这个基类就行,不用一个个改枚举值。
# base_enum.py from enum import Enum, auto class PrefixedEnum(Enum): def __str__(self): # 取当前枚举类所在的模块名当前缀 module_prefix = self.__class__.__module__.split('.')[-1] return f"{module_prefix}-{self.name}" def __repr__(self): return self.__str__()
然后在各个模块里用这个基类:
# foo.py from base_enum import PrefixedEnum, auto class Ids(PrefixedEnum): some_id = auto() # 其他枚举值随便加...
# bar.py from base_enum import PrefixedEnum, auto class Ids(PrefixedEnum): some_id = auto() # 其他枚举值...
测试代码(baz.py):
from foo import Ids as FooIds from bar import Ids as BarIds print(FooIds.some_id) # 输出: foo-some_id print(BarIds.some_id) # 输出: bar-some_id
方案2:自定义元类改枚举值本身
要是你不仅需要打印的时候带前缀,连枚举值的value都要带前缀,就用自定义元类,在枚举类创建的时候自动处理所有成员:
# base_enum.py from enum import EnumMeta, Enum, auto class PrefixedEnumMeta(EnumMeta): def __new__(cls, name, bases, attrs): # 拿模块名当前缀 module_prefix = attrs['__module__'].split('.')[-1] # 遍历所有属性,处理枚举成员 for attr_name, attr_value in list(attrs.items()): # 跳过下划线开头的特殊属性,只处理枚举值 if not attr_name.startswith('_') and isinstance(attr_value, int): # 把auto()生成的int值替换成带前缀的字符串 attrs[attr_name] = f"{module_prefix}-{attr_name}" return super().__new__(cls, name, bases, attrs) class PrefixedEnum(Enum, metaclass=PrefixedEnumMeta): pass
然后模块里这么用:
# foo.py from base_enum import PrefixedEnum class Ids(PrefixedEnum): some_id = auto() # 这里auto()会被自动换成"foo-some_id" # 其他枚举值...
要是想让print()直接输出带前缀的value,再给基类加个__str__:
class PrefixedEnum(Enum, metaclass=PrefixedEnumMeta): def __str__(self): return self.value
这样测试的时候:
from foo import Ids as FooIds print(FooIds.some_id.value) # 输出: foo-some_id print(FooIds.some_id) # 输出: foo-some_id
两种方案怎么选
- 方案1只改字符串显示,不碰枚举值本身,适合只是打印或日志里需要区分的场景,对原有代码逻辑影响最小。
- 方案2直接修改枚举值的
value,适合需要把这个带前缀的值当唯一标识存起来或者传给其他系统的场景。
内容的提问来源于stack exchange,提问作者David Owens
相关产品推荐
相关产品推荐

