在Python中将字符串转换为枚举
我想知道将字符串转换(反序列化)为Python的枚举类的正确方法是什么。似乎是在Python中将字符串转换为枚举,python,string,serialization,enums,type-conversion,Python,String,Serialization,Enums,Type Conversion,我想知道将字符串转换(反序列化)为Python的枚举类的正确方法是什么。似乎是getattr(YourEnumType,str)完成了这项工作,但我不确定它是否足够安全 更具体地说,我想将'debug'字符串转换为如下所示的枚举对象: class BuildType(Enum): debug = 200 release = 400 或者您需要将字符串转换为已知的枚举吗 class MyEnum(Enum): a = 'aaa' b = 123 print(My
getattr(YourEnumType,str)
完成了这项工作,但我不确定它是否足够安全
更具体地说,我想将'debug'
字符串转换为如下所示的枚举对象:
class BuildType(Enum):
debug = 200
release = 400
或者您需要将字符串转换为已知的枚举吗
class MyEnum(Enum):
a = 'aaa'
b = 123
print(MyEnum('aaa'), MyEnum(123))
或:
此功能已内置于枚举[1]中:
>>> from enum import Enum
>>> class Build(Enum):
... debug = 200
... build = 400
...
>>> Build['debug']
<Build.debug: 200>
[1] 官方文档:另一种选择(如果字符串未将1-1映射到枚举案例,则特别有用)是向枚举添加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\u type=QuestionType。从\u str('singleSelect')
我只想通知您,这在python 3.6中不起作用
class MyEnum(Enum):
a = 'aaa'
b = 123
print(MyEnum('aaa'), MyEnum(123))
您必须像这样以元组的形式提供数据
MyEnum(('aaa',))
编辑:
事实证明这是错误的。感谢一位评论者指出了我的错误这是对@rogueleader答案的改进:
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
我的类似Java的问题解决方案。希望它能帮助别人
类签名方法(枚举):
电子邮件=自动(),
GOOGLE=auto()
@类方法
def值_(cls,值):
对于cls中的k,v.\u成员\u.items():
如果k==value.upper():
返回v
sim=签名方法(“电子邮件”)的值
assert sim==SignInMethod.EMAIL
断言sim.name==“电子邮件”
断言isinstance(sim、SignInMethod)
由于MyEnum['dontexist']
将导致错误keyrerror:'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')
将您的类签名更改为:
类构建类型(str,Enum):
我的意思是我想将调试
字符串转换成这样的枚举:python类BuildType(enum):debug=200 release=400
伟大的提示!使用\uuuu dict\uuuu
是否与getattr
相同?我担心名称与内部Python属性的冲突…哦。。。是,它与getattr
相同。我看不出名称冲突的原因。您不能将关键字设置为类的字段。如果输入需要清理,那么回退值如何?类似于Build.get('非法',Build.debug)
?@Hetzroni:Enum
的东西没有.get()
方法,但是你可以根据需要添加一个,或者只是创建一个基Enum
类并始终从中继承。@Hetzroni:根据“请求原谅,而不是请求许可”原则,您可以始终将访问封装在try/except-KeyError子句中以返回默认值(正如Ethan所提到的,可以选择将其封装在您自己的函数/方法中)。这里值得注意的是,如果将其用于序列化/反序列化,请序列化此属性的name
属性,因此使用Build.debug.name
而不是str(Build.debug)
以使这种查找工作(否则它会尝试在反序列化端查找不存在的Build.debug
。@Dragonborn调用Build('debug')将不起作用
。类构造函数必须接受该值,即本例中的200
或400
。要传递名称,必须使用方括号,正如答案所述。使用Python 3.6.6,我无法重现此行为。我想您可能在测试时犯了错误(我知道我第一次检查此项时就犯了错误)。如果您意外地在每个元素后放置了一个,
(逗号)(就像元素是一个列表一样),那么它会将每个元素视为一个元组。(即a='aaa',
实际上与a=('aaa',)
)你是对的,这是我代码中的不同错误。我不知何故认为你需要在定义枚举时将,
放在每行后面,将值转换为元组,如果你发现自己经常这样做的话:有没有办法覆盖\uu getitem\uuuuu
或其他内置方法?有没有办法改变r编写\uuu getitem\uuu
或其他内置方法?
MyEnum(('aaa',))
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
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')