Python 中基于字符串的枚举

新手上路,请多包涵

要封装我正在使用的状态列表 enum 模块:

 from enum import Enum

class MyEnum(Enum):
    state1='state1'
    state2 = 'state2'

state = MyEnum.state1
MyEnum['state1'] == state  # here it works
'state1' == state  # here it does not throw but returns False (fail!)

但是,问题是我需要在我的脚本的许多上下文中无缝地将值用作字符串,例如:

 select_query1 = select(...).where(Process.status == str(MyEnum.state1))  # works but ugly

select_query2 = select(...).where(Process.status == MyEnum.state1)  # throws exeption

如何避免调用额外的类型转换(上面的 str(state) )或基础值( state.value )?

原文由 sophros 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.1k
2 个回答

似乎从 str 类同时继承 Enum 就足够了:

 from enum import Enum

class MyEnum(str, Enum):
    state1 = 'state1'
    state2 = 'state2'

棘手的部分是继承链中类 的顺序 _很重要_,如下所示:

 class MyEnum(Enum, str):
    state1 = 'state1'
    state2 = 'state2'

投掷:

 TypeError: new enumerations should be created as `EnumName([mixin_type, ...] [data_type,] enum_type)`

使用正确的类,可以对 MyEnum 执行以下操作:

 print('This is the state value: ' + state)


作为旁注,似乎 格式化字符串 不需要特殊的继承技巧,它甚至适用于 Enum 仅继承:

 msg = f'This is the state value: {state}'  # works without inheriting from str

原文由 sophros 发布,翻译遵循 CC BY-SA 4.0 许可协议

通过阅读文档(即,我没有尝试,因为我使用的是旧版本的 Python,但我相信文档),自 Python 3.11 以来,您可以执行以下操作:

 from enum import StrEnum

class Directions(StrEnum):
    NORTH = 'north',    # notice the trailing comma
    SOUTH = 'south'

print(Directions.NORTH)
>>> north

请参阅 文档设计讨论 以进一步了解。

如果你运行的是 python 3.6+ ,执行 pip install StrEnum ,然后你可以执行以下操作(经我确认):

 from strenum import StrEnum

class URLs(StrEnum):
    GOOGLE = 'www.google.com'
    STACKOVERFLOW = 'www.stackoverflow.com'

print(URLs.STACKOVERFLOW)

>>> www.stackoverflow.com

您可以 在此处 阅读更多相关信息。

此外,文档中也提到了这一点——如何基于其他类创建自己的枚举:

虽然 IntEnum 是枚举模块的一部分,但独立实现起来非常简单:

class IntEnum(int, Enum): pass 这演示了如何定义类似的派生枚举;例如,混合在 str 而不是 int 中的 StrEnum。

一些规则:

当对 Enum 进行子类化时,混合类型必须出现在基序列中的 Enum 本身之前,如上面的 IntEnum 示例所示。

虽然 Enum 可以有任何类型的成员,但是一旦你混合了一个额外的类型,所有的成员都必须有那个类型的值,例如上面的 int。此限制不适用于仅添加方法而不指定其他类型的混合。

当混合了另一种数据类型时,value 属性与枚举成员本身不同,尽管它是等价的并且比较相等。

%风格的格式化:%s和%r分别调用了Enum类的 str ()和 repr ();其他代码(例如 IntEnum 的 %i 或 %h)将枚举成员视为其混合类型。

格式化字符串文字、str.format() 和 format() 将使用混合类型的 format () 除非 str () 或 format () 在子类中被覆盖,在这种情况下将使用被覆盖的方法或 Enum 方法.使用 !s 和 !r 格式代码强制使用 Enum 类的 str () 和 repr () 方法。

来源: https ://docs.python.org/3/library/enum.html#others

原文由 Elyasaf755 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题