Python - 在创建过程中扩展枚举字段

Python - extend enum fields during creation

提问人:Sergey 提问时间:11/18/2023 最后编辑:Sergey 更新时间:11/21/2023 访问量:95

问:

是否可以在创建过程中扩展枚举? 例:

class MyEnum(enum.StrEnum):
    ID = "id"
    NAME = "NAME

创建此枚举后,我需要包含以下字段:

ID = "id"
NAME = "name"
ID_DESC = "-id"
NAME_DESC = "-name"

我需要它来为 FastAPI 项目创建自定义排序枚举

现在我有了创建新枚举的下一种方法

NewEnum = enum.StrEnum(
    f"{name.title()}OrderingEnum",
    [
        (
            f"{ordering_field.upper()}_DESC"
            if ordering_field.startswith("-")
            else ordering_field.upper(),
            ordering_field,
        )
        for ordering_field in itertools.chain(
            values,
            [f"-{field}" for field in values],
        )
    ],
)

但我需要自动执行此操作,因为每个具有模型的模块都有相似的枚举。也许这可以解决我的问题,用于我的枚举类或覆盖方法,但我还没有找到可行的解决方案MetaClass__new__

Python 枚举元

评论

0赞 Barmar 11/18/2023
在我看来,当你应该使用字典时,你正在使用枚举。
0赞 Sergey 11/18/2023
我使用枚举生成 API 方案上的排序字段。这样,前端可以看到所有可用的排序字段,pydantic 将对无效值引发验证错误multiple select
0赞 Barmar 11/21/2023
如果字段是动态添加的,它能做到这一点吗?
0赞 Sergey 11/21/2023
@Barmar字段只添加一次,枚举在添加额外字段后使用。现在我像我的问题中的示例一样做了它,但它有很多复制,因为我需要为一些模型提供类似的枚举。我想以其他方式扩展枚举(但也许这是不可能的)
0赞 Sergey 11/21/2023
也许我的问题标题不正确。我重命名了这个(删除了单词)dinamically

答:

1赞 Ethan Furman 11/21/2023 #1

增强 of(过去是,现在仍然将其作为别名)将完成这项工作:__new__EnumTypeEnumMeta

from enum import EnumMeta, StrEnum

class IDEnumMeta(EnumMeta):
    def __new__(metacls, cls, bases, classdict, **kwds):
        # add new entries to classdict
        for name in list(classdict._member_names):
            classdict[f'{name}_DESC'] = f'-{classdict[name]}'
        return super().__new__(metacls, cls, bases, classdict, **kwds)

class IDEnum(StrEnum, metaclass=IDEnumMeta):
    pass

并在使用中:

>>> class MyEnum(IDEnum):
...     ID = 'id'
...     NAME = 'name'

>>> list(MyEnum)
[<MyEnum.ID: 'id'>, <MyEnum.NAME: 'name'>, <MyEnum.ID_DESC: '-id'>, <MyEnum.NAME_DESC: '-name'>]

此答案目前使用 private 及其属性,但它们将在 3.13 中公开。_EnumDict_member_names


披露:我是 Python stdlib 枚举、enum34 向后移植高级枚举 (aenum 库的作者。

评论

0赞 Sergey 11/22/2023
你让我开心!谢谢!