如何正确地将字符串转换为相应的枚举
子类实例?似乎使用getattr(YourEnumType, str)
可以完成任务,但我不确定它是否足够安全。
例如,假设我有一个枚举类型如下:
class BuildType(Enum):
debug = 200
release = 400
如何从字符串'debug'
获得BuildType.debug
的结果?
如何正确地将字符串转换为相应的枚举
子类实例?似乎使用getattr(YourEnumType, str)
可以完成任务,但我不确定它是否足够安全。
例如,假设我有一个枚举类型如下:
class BuildType(Enum):
debug = 200
release = 400
如何从字符串'debug'
获得BuildType.debug
的结果?
Enum
中了。>>> from enum import Enum
>>> class Build(Enum):
... debug = 200
... build = 400
...
>>> Build['debug']
<Build.debug: 200>
an_enum = input('Which type of build?')
build_type = Build[an_enum.lower()]
Build.get('illegal', Build.debug)
这样的形式? - HetzroniEnum
没有 .get()
方法,但是你可以根据需要添加一个或者只需创建一个基础的 Enum
类并继承它。 - Ethan FurmanBuild('debug')
不起作用。在这个例子中,类构造函数必须采用值,即 200
或 400
。如果要传递名称,则必须使用方括号,就像答案已经指出的那样。 - Arthur Tacca_missing_
。 - rysson另一种选择(特别适用于您的字符串与枚举实例不是1对1映射的情况)是向您的Enum
添加一个staticmethod
,例如:
class QuestionType(enum.Enum):
MULTI_SELECT = "multi"
SINGLE_SELECT = "single"
@staticmethod
def from_str(label):
if label in ('single', 'singleSelect'):
return QuestionType.SINGLE_SELECT
elif label in ('multi', 'multiSelect'):
return QuestionType.MULTI_SELECT
else:
raise NotImplementedError
那么你可以执行 question_type = QuestionType.from_str('singleSelect')
__getitem__
或其他内置方法? - ClementWalterenum.Enum
已经为你做了这个。你可以子类化enum.Enum
的元类,也就是enum.EnumType
,并重写它的__getitem__
方法 - 但你真的需要它执行与默认值不同的操作吗? - Karl Knechteldef custom_enum(typename, items_dict):
class_definition = """
from enum import Enum
class {}(Enum):
{}""".format(typename, '\n '.join(['{} = {}'.format(k, v) for k, v in items_dict.items()]))
namespace = dict(__name__='enum_%s' % typename)
exec(class_definition, namespace)
result = namespace[typename]
result._source = class_definition
return result
MyEnum = custom_enum('MyEnum', {'a': 123, 'b': 321})
print(MyEnum.a, MyEnum.b)
或者你需要将字符串转换为 已知 枚举类型吗?
class MyEnum(Enum):
a = 'aaa'
b = 123
print(MyEnum('aaa'), MyEnum(123))
或者:
class BuildType(Enum):
debug = 200
release = 400
print(BuildType.__dict__['debug'])
print(eval('BuildType.debug'))
print(type(eval('BuildType.debug')))
print(eval(BuildType.__name__ + '.debug')) # for work with code refactoring
debug
字符串转换为这样的枚举:class BuildType(Enum):
debug = 200
release = 400
- Vladius__dict__
和getattr
是一样的吗?我担心会与Python内部属性发生名称冲突.... - Vladiusgetattr
一样。我看不出有名称冲突的理由。你只是不能将关键字设置为类的字段。 - ADR这是我对问题的类Java解决方案。希望能对某些人有所帮助...
from enum import Enum, auto
class SignInMethod(Enum):
EMAIL = auto(),
GOOGLE = auto()
@classmethod
def value_of(cls, value):
for k, v in cls.__members__.items():
if k == value:
return v
else:
raise ValueError(f"'{cls.__name__}' enum not found for '{value}'")
sim = SignInMethod.value_of('EMAIL')
assert sim == SignInMethod.EMAIL
assert sim.name == 'EMAIL'
assert isinstance(sim, SignInMethod)
# SignInMethod.value_of("invalid sign-in method") # should raise `ValueError`
SignInMethod('EMAIL')
方法将具有相同的效果 - Rafael Gomes Franciscoclass LogLevel(IntEnum):
critical = logging.CRITICAL
fatal = logging.FATAL
error = logging.ERROR
warning = logging.WARNING
info = logging.INFO
debug = logging.DEBUG
notset = logging.NOTSET
def __str__(self):
return f'{self.__class__.__name__}.{self.name}'
@classmethod
def _missing_(cls, value):
if type(value) is str:
value = value.lower()
if value in dir(cls):
return cls[value]
raise ValueError("%r is not a valid %s" % (value, cls.__name__))
例子:
print(LogLevel('Info'))
print(LogLevel(logging.WARNING))
print(LogLevel(10)) # logging.DEBUG
print(LogLevel.fatal)
print(LogLevel(550))
输出:
LogLevel.info
LogLevel.warning
LogLevel.debug
LogLevel.critical
ValueError: 550 is not a valid LogLevel
StrEnum
。当然,你也需要将值替换为字符串,因为它是根据值而不是名称进行键入的(对于值使用enum.auto()
是一个不错的解决方案)。import enum
class BuildType(enum.StrEnum):
debug = "200"
release = "400"
print(BuildType("debug"))
BuildType["debug"]
的StrEnum,将始终导致KeyError,并且您必须使用您在这里展示的BuildType("debug")
语法。这恰好与将字符串分配为值的常规Enum完全相反。 - undefined将你的类签名更改为以下内容:
class BuildType(str, Enum):
@rogueleaderr的回答有所改进:
最初的回答:
class QuestionType(enum.Enum):
MULTI_SELECT = "multi"
SINGLE_SELECT = "single"
@classmethod
def from_str(cls, label):
if label in ('single', 'singleSelect'):
return cls.SINGLE_SELECT
elif label in ('multi', 'multiSelect'):
return cls.MULTI_SELECT
else:
raise NotImplementedError
__getitem__
或其他内置方法? - ClementWalter由于 MyEnum['dontexist']
会导致错误 KeyError: 'dontexist'
,您可能希望静默失败(例如,返回 None)。在这种情况下,您可以使用以下静态方法:
class Statuses(enum.Enum):
Unassigned = 1
Assigned = 2
@staticmethod
def from_str(text):
statuses = [status for status in dir(
Statuses) if not status.startswith('_')]
if text in statuses:
return getattr(Statuses, text)
return None
Statuses.from_str('Unassigned')
如果您想通过名称访问枚举成员,请使用项访问:
>>> from enum import Enum
>>> class Build(Enum):
... debug = 200
... build = 400
...
>>> Build['debug']
<Build.debug: 200>
它对于意外的名称值引发 KeyError
。
对于下面的 Enum 类,其中的值是字符串:
class BuildType(Enum):
debug = 'debug'
release = 'release'
>>> BuildType('debug')
<BuildType.debug: 'debug'>