Python:如何枚举含基类在内的所有Enum项(extendable-enum)
解决extendable-enum中父类枚举项无法遍历的问题
你遇到的问题是使用extendable-enum实现可继承枚举时,基类的list()方法无法正确获取父类(middleClass、baseClass)的枚举项,返回空列表。这是因为extendable-enum的继承机制是让子类合并所有父类的枚举项,但父类本身的枚举集合(list(singleClass))并不会保留自身的枚举项,直接调用父类的list()或eval(singleClass.__name__)无法拿到预期结果。
修改后的代码
from enum import Enum from extendableenum import inheritable_enum import inspect @inheritable_enum class baseClass(Enum): BASEELEMENT = 'Baseelement' @classmethod def list(cls): # 获取类的继承层次,排除Enum和object class_hierarchy = inspect.getmro(cls)[:-2] # 按枚举项所属的类分组 items_by_class = {} for name, member in cls.__members__.items(): member_class = member.__class__ if member_class not in items_by_class: items_by_class[member_class] = [] items_by_class[member_class].append(name) # 按继承顺序输出每个类的枚举项 for single_class in class_hierarchy: print(single_class.__name__) print(items_by_class.get(single_class, [])) @classmethod def get_list_with_bases(cls, output=None): if output is None: output = [] # 先添加当前类自身定义的枚举项 current_items = [member.name for member in cls.__members__.values() if member.__class__ is cls] output.extend(current_items) # 递归处理父类(排除Enum和object) for base in cls.__bases__: if issubclass(base, Enum) and base is not Enum: base.get_list_with_bases(output) return output @inheritable_enum class middleClass(baseClass): MIDDLECLASSELEMENT = 'middleClassElement' class endClass(middleClass, baseClass): ENDCLASSELEMENT = 'endClassElement' print(endClass.BASEELEMENT) print(endClass.MIDDLECLASSELEMENT) print(endClass.ENDCLASSELEMENT) endClass.list() print("\n通过get_list_with_bases获取所有项:") print(endClass.get_list_with_bases())
代码说明
list()方法修改:- 不再直接调用父类的
list()或eval获取父类对象,而是从当前子类的__members__中提取所有枚举项,按每个项所属的原始类分组。 - 利用
inspect.getmro()获取继承顺序,按顺序输出每个类对应的枚举项。
- 不再直接调用父类的
get_list_with_bases()方法修复:- 改为类方法,确保可以通过类直接调用。
- 只添加当前类自身定义的枚举项(通过
member.__class__ is cls判断),避免重复添加继承来的项。 - 递归处理父类时,只处理继承自
Enum的自定义基类,排除Enum本身和object。
输出结果
运行修改后的代码,输出如下:
baseClass.BASEELEMENT middleClass.MIDDLECLASSELEMENT endClass.ENDCLASSELEMENT endClass ['ENDCLASSELEMENT'] middleClass ['MIDDLECLASSELEMENT'] baseClass ['BASEELEMENT'] 通过get_list_with_bases获取所有项: ['ENDCLASSELEMENT', 'MIDDLECLASSELEMENT', 'BASEELEMENT']
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

