sop*_*ros 12 python string enums python-3.x
要封装我使用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!)
Run Code Online (Sandbox Code Playgroud)
但是,问题是我需要在脚本的许多上下文中无缝地将值用作字符串,例如:
select_query1 = select(...).where(Process.status == str(MyEnum.state1)) # works but ugly
select_query2 = select(...).where(Process.status == MyEnum.state1) # throws exeption
Run Code Online (Sandbox Code Playgroud)
如何避免调用额外的类型转换(str(state)
以上)或底层值(state.value
)?
Ely*_*755 122
通过阅读文档(即,我没有尝试它,因为我使用旧版本的 Python,但我信任文档),从Python 3.11开始,您可以执行以下操作:
\nfrom enum import StrEnum\n\nclass Directions(StrEnum):\n NORTH = \'north\'\n SOUTH = \'south\'\n\nprint(Directions.NORTH)\n>>> north\n
Run Code Online (Sandbox Code Playgroud)\n请注意,看起来在子类化 StrEnum 时,将枚举字段定义为单值元组根本没有区别,并且也将被视为字符串,如下所示:
\nclass Directions(StrEnum):\n NORTH = \'north\', # notice the trailing comma\n SOUTH = \'south\'\n
Run Code Online (Sandbox Code Playgroud)\n\n如果您运行的是python 3.6+,请执行pip install StrEnum
,然后您可以执行以下操作(经我确认):
from strenum import StrEnum\n\nclass URLs(StrEnum):\n GOOGLE = \'www.google.com\'\n STACKOVERFLOW = \'www.stackoverflow.com\'\n\nprint(URLs.STACKOVERFLOW)\n\n>>> www.stackoverflow.com\n
Run Code Online (Sandbox Code Playgroud)\n你可以在这里读更多关于它的内容。
\n\n\n虽然 IntEnum 是 enum 模块的一部分,但独立实现\n会非常简单:
\nclass IntEnum(int, Enum):\npass 这演示了如何定义类似的派生枚举;例如,混合了 str 而不是 int 的 StrEnum。
\n一些规则:
\n当对 Enum 进行子类化时,混合类型必须在基数序列中出现在 Enum 本身之前,如上面的 IntEnum 示例所示。
\n虽然 Enum 可以具有任何类型的成员,但一旦混合了其他\n类型,所有成员都必须具有该类型的值,例如上面的 int。\n此限制不适用于仅添加方法和\ndon\ 的混合。 xe2\x80\x99t 指定另一种类型。
\n当混合另一种数据类型时,值属性与枚举成员本身不同,尽管它是等效的并且比较相等。
\n%式格式:%s和%r分别调用Enum类\xe2\x80\x99s str ()和\n repr ();其他代码(例如 IntEnum 的 %i 或 %h)将枚举成员视为其混合类型。
\n格式化字符串文字、str.format() 和 format() 将使用混合类型\xe2\x80\x99s format (),除非在子类中重写了str () 或format (),在这种情况下将使用重写的方法或\nEnum 方法。使用 !s 和 !r 格式代码强制使用 Enum 类\xe2\x80\x99s str () 和repr () 方法。
\n
来源: https: //docs.python.org/3/library/enum.html#others
\nsop*_*ros 27
似乎同时从str
类继承就足够了Enum
:
class MyEnum(str, Enum):
state1='state1'
state2 = 'state2'
Run Code Online (Sandbox Code Playgroud)
棘手的部分是继承链中类的顺序很重要,因为:
class MyEnum(Enum, str):
state1='state1'
state2 = 'state2'
Run Code Online (Sandbox Code Playgroud)
抛出:
TypeError: new enumerations should be created as `EnumName([mixin_type, ...] [data_type,] enum_type)`
Run Code Online (Sandbox Code Playgroud)
使用正确的类,以下操作就MyEnum
可以了:
print('This is the state value: ' + state)
Run Code Online (Sandbox Code Playgroud)
作为旁注,似乎格式化字符串不需要特殊的继承技巧,即使Enum
仅适用于继承:
msg = f'This is the state value: {state}' # works without inheriting from str
Run Code Online (Sandbox Code Playgroud)
小智 20
使用该值有什么问题?
恕我直言,除非将 Python 版本 3.11 与 StrEnum 一起使用,否则我只需重写__str__(self)
正确的 Enum 类中的方法:
class MyStrEnum(str, Enum):
OK = 'OK'
FAILED = 'FAILED'
def __str__(self) -> str:
return self.value
Run Code Online (Sandbox Code Playgroud)
最好的
和auto
定义枚举:
from enum import auto
from my_utils import AutoStrEnum
class MyEnum(AutoStrEnum):
STATE_1 = auto()
STATE_2 = auto()
Run Code Online (Sandbox Code Playgroud)
用它:
MyEnum.STATE_1 == "STATE_1" # True
Run Code Online (Sandbox Code Playgroud)
my_utils.py
:
from enum import Enum
class AutoStrEnum(str, Enum):
"""
StrEnum where enum.auto() returns the field name.
See https://docs.python.org/3.9/library/enum.html#using-automatic-values
"""
@staticmethod
def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str:
return name
Run Code Online (Sandbox Code Playgroud)
str
虽然和之间的 mixin 类Enum
可以解决这个问题,但您还应该始终考虑为该工作找到合适的工具。
有时,正确的工具很容易就是带有字符串值的 MODULE_CONSTANT 。例如,logging
有一些常量,如 DEBUG、INFO 等,具有有意义的值 - 即使它们int
在本例中是 s。
枚举是一个很好的工具,我经常使用它们。然而,它们主要是为了与同一枚举的其他成员进行比较,这就是为什么将它们与字符串等进行比较需要您跳过一个额外的环节。
.name
如果关联的字符串值是有效的 Python 名称,那么您可以使用如下属性获取枚举成员的名称:
from enum import Enum
class MyEnum(Enum):
state1=0
state2=1
print (MyEnum.state1.name) # 'state1'
a = MyEnum.state1
print(a.name) # 'state1'
Run Code Online (Sandbox Code Playgroud)
如果关联的字符串值是任意字符串,那么您可以这样做:
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'
Run Code Online (Sandbox Code Playgroud)
在线尝试:https: //repl.it/@sytelus/enumstrtest
归档时间: |
|
查看次数: |
13700 次 |
最近记录: |