使用Python 3.4我想测试Enum类是否包含具有特定名称的成员。
示例:
class Constants(Enum):
One = 1
Two = 2
Three = 3
print(Constants['One'])
print(Constants['Four'])
给出:
Constants.One
File "C:\Python34\lib\enum.py", line 258, in __getitem__
return cls._member_map_[name]
KeyError: 'Four'
我可以抓住KeyError
并将异常作为存在的指示,但也许有更优雅的方式?
答案 0 :(得分:32)
您可以使用Enum.__members__
- an ordered dictionary mapping names to members:
In [12]: 'One' in Constants.__members__
Out[12]: True
In [13]: 'Four' in Constants.__members__
Out[13]: False
答案 1 :(得分:16)
我会说这属于EAFP(更容易要求宽恕而非许可),这是一个相对独特的Python概念。
比获得许可更容易请求宽恕。这种常见的Python编码风格假设存在有效的键或属性,并且如果假设被证明是错误则捕获异常。这种干净和快速的风格的特点是存在许多try和except语句。该技术与许多其他语言(如C。
)共有的LBYL风格形成对比
这与LBYL(跳跃前看)相反,当你说你正在寻找更优雅的方式时,这就是我想你想要的。"
在你跳跃之前先看看。这种编码风格在进行调用或查找之前明确地测试前置条件。这种风格与EAFP方法形成对比,其特点是存在许多if语句。
在多线程环境中,LBYL方法可能会冒险在“外观”和“跳跃”之间引入竞争条件。例如,代码,如果映射中的键:如果另一个线程在测试之后但在查找之前从映射中删除了键,则返回映射[key]可能会失败。这个问题可以通过锁定或使用EAFP方法来解决。
因此,根据文档,实际上最好使用try
/ except
块来解决您的问题。
使用try
/ except
块来捕获KeyError
例外。
答案 2 :(得分:4)
可以使用以下内容测试名称是否存在:
if any(x for x in Constants if x.name == "One"):
# Exists
else:
# Doesn't Exist
使用x.value测试枚举值:
if any(x for x in Constants if x.value == 1):
# Exists
else:
# Doesn't Exist
答案 3 :(得分:3)
为了提高可读性,您可以将以上建议作为类方法。 例如:
class Constants(Enum):
One = 1
Two = 2
Three = 3
@classmethod
def has_key(cls, name):
return name in cls.__members__ # solution above 1
# return any(x for x in cls if x.name == name) # or solution above 2
要使用:
In [6]: Constants.has_key('One')
Out[6]: True
In [7]: Constants.has_key('Four')
Out[7]: False
答案 4 :(得分:0)
有点明显,所以不确定为什么没有提到它,可能有一些我没有想到的陷阱,但 hasattr
可以以编程方式迭代它们并检查成员资格:
class DataSource(Enum):
ENCYCLOPEDIA = "encyclopedia"
NEWSPAPER = "newspaper"
BOOK = "book"
MAGAZINE = "magazine"
input_sources = [
{"dataSource": "encyclopedia"},
{"dataSource": "wikipedia"},
{"dataSource": None}
]
data_sources = [set(
datum['dataSource']
for datum in input_sources
if datum['dataSource'] is not None
and hasattr(DataSource, datum.get('dataSource', '').upper())
)]
输出为:
[ ]: data_sources
[51]: [{'encyclopedia'}]