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>]