多分支逻辑的标记用法

Flag usage for multibranch logic

我需要做这样的事情:

from enum import Flag, auto

class WISENESS(Flag):
    Y = auto()
    M = auto()
    D = auto()
    YM = Y | M
    YD = Y | D
    MD = M | D
    YMD = Y | M | D

first_case = WISENESS.Y

first_case == WISENESS.Y # True
first_case == WISENESS.M # False
first_case == WISENESS.D # False

###

second_case = WISENESS.YD

second_case == WISENESS.Y # True
second_case == WISENESS.M # False
second_case == WISENESS.D # True

####

third_case = WISENESS.YMD

third_case == WISENESS.Y # True
third_case == WISENESS.M # True
third_case == WISENESS.D # True

即根据标志值,在某些情况下它会是真的。例如,我可能需要对所有可能的情况执行一个操作,或者只对其中两个进行操作。 就像这里的这个例子:

if WISENESS.Y:
    do_something_in_case_of_Y_or_MY_or_YD_or_YMD()
if WISENESS.M:
    do_something_in_case_of_M_or_MD_or_YM_or_YMD()
if WISENESS.D:
    do_something_in_case_of_D_or_MD_or_YD_or_YMD()

我尝试使用标准库中枚举模块中的 Flag,猜测它在这种情况下可以帮助我,但要么我不明白它是如何工作的,要么我必须以不同的方式实现我的目标。

注意:请参阅 Ethan Furman 的回答以了解解决此问题的正确 Pythonic 方法。这个答案解释了如何使用按位运算符检查标志包含,这在其他情况和其他编程语言中很有用。

要检查值中是否包含标志,您应该使用按位运算符,特别是 &.

wiseness = WISENESS.MD
if wiseness & WISENESS.Y == WISENESS.Y:
    print('contains Y')
if wiseness & WISENESS.M == WISENESS.M:
    print('contains M')
if wiseness & WISENESS.D == WISENESS.D:
    print('contains D')

& AND 运算符通过返回两个提供的值中哪些位相同来工作。在您的枚举定义中,auto() 提供值 Y = 1M = 2D = 4,其二进制形式为 000100100100 分别。然后,组合值包含它们包含的每个标志的一个位,由 | OR 运算符形成,例如 MD = 0010 | 0100 = 0110.

然后在上面的代码中,wiseness0110,进行以下 & 检查:

wiseness & WISENESS.Y --> 0110 & 0001 = 0000 --> != WISENESS.Y
wiseness & WISENESS.M --> 0110 & 0010 = 0010 --> == WISENESS.M
wiseness & WISENESS.D --> 0110 & 0100 = 0100 --> == WISENESS.D

检查 Flag 成员资格的内置方法是使用标准 Python in 运算符:

>>> second_case in WISENESS.Y
True

你的最后一个例子是:

some_flag = ...

if WISENESS.Y in some_flag:
    do_something_in_case_of_Y_or_MY_or_YD_or_YMD()
if WISENESS.M in some flag:
    do_something_in_case_of_M_or_MD_or_YM_or_YMD()
if WISENESS.D in some flag:
    do_something_in_case_of_D_or_MD_or_YD_or_YMD()