首页 > 解决方案 > 如何遍历枚举标志子类中的 *distinct* 标志?

问题描述

我必须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

有没有办法只遍历不同的标志,而不是命名的组合?IE:

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

标签: pythonpython-3.x

解决方案


一种愚蠢的解决方案,但您可以使用Bit Twiddling Hacks 测试整数是 2 的幂来仅找到单个位标志。如果您的标志是现有标志的别名,而不是它们的组合,这将包括它们,但它会过滤掉任何没有精确设置一位的标志:

def distinct_flags(enm):
    return [x for x in enm if (x.value & (x.value - 1)) == 0]

使用时会得到以下结果(因为我在 IPython 中运行它,所以稍微漂亮一些):

>>> distinct_flags(DataSubset)
[<DataSubset.TRAIN: 1>,
 <DataSubset.TEST: 2>,
 <DataSubset.VALIDATION: 4>,
 <DataSubset.EXCLUDED: 8>]

您只需get_subsets围绕该功能构建您的函数,或者将两个功能位(过滤到单个标志和包含在提供的子集中的标志)合并到if现有代码中的条件中。


推荐阅读