Python 如何遍历枚举标志子类中的*distinct*标志?
我有一个Python 如何遍历枚举标志子类中的*distinct*标志?,python,python-3.x,Python,Python 3.x,我有一个enum来表示数据集的不同子集,以及这些子集的组合: from enum import Flag, auto class DataSubset(Flag): TRAIN = auto() TEST = auto() VALIDATION = auto() EXCLUDED = auto() TRAIN_TEST = TRAIN | TEST ALL_INCLUDED = TRAIN_TEST | VALIDATION ALL =
enum
来表示数据集的不同子集,以及这些子集的组合:
from enum import Flag, auto
class DataSubset(Flag):
TRAIN = auto()
TEST = auto()
VALIDATION = auto()
EXCLUDED = auto()
TRAIN_TEST = TRAIN | TEST
ALL_INCLUDED = TRAIN_TEST | VALIDATION
ALL = ALL_INCLUDED | EXCLUDED
有没有一种方法可以只遍历不同的标志,而不遍历命名的组合?i、 e:
[DataSubset.TRAIN, DataSubset.TEST, DataSubset.VALIDATION, DataSubset.EXCLUDED]
目标是能够做到以下几点:
def get_subsets(subset):
return [sub for sub in DataSubset.distinct_flags if sub in subset]
然后:
>>> get_subsets(DataSubset.TRAIN)
[DataSubset.TRAIN]
>>> get_subsets(DataSubset.TRAIN_TEST)
[DataSubset.TRAIN, DataSubset.TEST]
>>> get_subsets(DataSubset.ALL)
[DataSubset.TRAIN, DataSubset.TEST, DataSubset.VALIDATION, DataSubset.EXCLUDED]
这是一种愚蠢的解决方案,但您可以使用查找单位标志。如果您的标志是现有标志的别名,而不是它们的组合,这将包括它们,但它将过滤掉任何不精确设置一位的标志:
def distinct_flags(enm):
return [x for x in enm if (x.value & (x.value - 1)) == 0]
当使用它时,会得到以下结果(因为我在IPython中运行它,所以稍微漂亮一些):
不同的标志(数据子集)
[,
,
,
]
您只需围绕该功能构建
get_子集
函数,或者将两个功能位(过滤到单个标志和包含在提供的子集中的标志)合并到现有代码中的if
条件中。我能够通过创建一个新元类、合并和
那么:
>>> print(list(DataSubset)
[<DataSubset.BURN_IN: 1>,
<DataSubset.TRAIN: 2>,
<DataSubset.TEST: 4>,
<DataSubset.HOLDOUT: 8>,
<DataSubset.EXCLUDED: 16>]
打印(列表(数据子集)
[,
,
,
,
]
注意:如果所有标志都是用
auto()
或所述标志的组合创建的,则不需要测试的和x.value!=0,因为标志的auto()
从1
开始;没有一个标志的值是0
(这不仅仅是实现细节,它是一个逻辑要求;否则,每个标志都将与值为0
的标志隐式联合)。
from enum import EnumMeta, Flag, auto
class DistinctFlag(EnumMeta):
def __iter__(cls):
for x in super().__iter__():
if (x.value & (x.value-1))==0 and x.value != 0:
yield x
class DataSubset(Flag, metaclass=DistinctFlag):
"""Enum to describe distinct subsets of a modeling dataset"""
BURN_IN = auto()
TRAIN = auto()
TEST = auto()
HOLDOUT = auto()
EXCLUDED = auto()
TRAIN_TEST = TRAIN | TEST
OBS = BURN_IN | TRAIN_TEST
ALL_INCLUDED = OBS | HOLDOUT
ALL = ALL_INCLUDED | EXCLUDED
>>> print(list(DataSubset)
[<DataSubset.BURN_IN: 1>,
<DataSubset.TRAIN: 2>,
<DataSubset.TEST: 4>,
<DataSubset.HOLDOUT: 8>,
<DataSubset.EXCLUDED: 16>]