Python中基于字符串的枚举
要封装我正在使用的Python中基于字符串的枚举,python,python-3.x,string,enums,Python,Python 3.x,String,Enums,要封装我正在使用的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!) 但是,问题是
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
)?似乎在Enum
的同时从str
类继承就足够了:
class MyEnum(str, Enum):
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
虽然
str
和Enum
之间的mixin类可以解决这个问题,但您也应该始终考虑为作业找到合适的工具
有时,正确的工具可能只是一个带有字符串值的MODULE_常量。例如,logging
有一些常量,如DEBUG、INFO等,这些常量具有有意义的值,即使在本例中它们是int
s
枚举是一个很好的工具,我经常使用它们。但是,它们主要用于与同一枚举的其他成员进行比较,这就是为什么将它们与字符串(例如字符串)进行比较需要您跳转到另一个环。尝试更改数据库中状态的数据类型以匹配枚举。某些数据库不允许,或者也尝试使用临时表副本。如果关联的字符串值是有效的Python名称,则可以使用
.name
属性获取枚举成员的名称,如下所示:
from enum import Enum
class MyEnum(Enum):
state1=0
state2=1
print (MyEnum.state1.name) # 'state1'
a = MyEnum.state1
print(a.name) # 'state1'
如果关联的字符串值是任意字符串,则可以执行以下操作:
class ModelNames(str, Enum):
gpt2 = 'gpt2'
distilgpt2 = 'distilgpt2'
gpt2_xl = 'gpt2-XL'
gpt2_large = 'gpt2-large'
print(ModelNames.gpt2) # 'ModelNames.gpt2'
print(ModelNames.gpt2 is str) # False
print(ModelNames.gpt2_xl.name) # 'gpt2_xl'
print(ModelNames.gpt2_xl.value) # 'gpt2-XL'
联机尝试此选项:只需使用。值:
MyEnum.state1.value == 'state1'
# True
MyEnum.state1.value
?对不起,这和我认为的str(state)
一样难看……什么类型是Testround.status
?您可以将其设置为MyEnum类型吗?您的示例代码'state1'==state
是错误的——该比较返回False
@EthanFurman:它不会抛出,但结果确实远远不能令人满意。谢谢更正。相关文档:请注意,astr
mixin可能会产生意外的副作用,例如(反)序列化行为;例如,请参阅创建的Enum
,这样就不需要不透明的模块常量。@EthanFurman那么为什么logging.DEBUG和friends没有被弃用?它们不会被弃用--它们将被相应的IntEnum
替换。标准策略是尽可能保持stdlib的稳定性,这意味着不必为了利用每一个新特性而大量重写它。到目前为止,http
,socket
和re
模块常量已经被替换(可能还有一些我现在不记得了)。的相关部分。哇,感觉我们已经很久没谈过了!这里的要点与我之前的评论有关:没有充分的理由不要重写stdlib。魔术字符串的情况更难解释,因为这些字符串通常是不言自明的。最有可能进行Enum
转换的模块是面向用户的整数常量(例如re
和http
)。另外,不转换stdlib的特定部分的一个重要原因是它是否在可以导入Enum
之前使用。这些都是不影响stdlib之外的代码的原因,我们这里不是在谈论数据库。这都是关于Python代码的。问题明确指出,调用.value
不是一个可接受的解决方案。
MyEnum.state1.value == 'state1'
# True