是否可以制作一个 class 来堆叠枚举标志?
Is it possible to make a class which lets you stack enum Flags?
我想尽可能使用命名常量,而不是提供文字值或带有大量布尔参数的冗长函数签名。
因此我喜欢蟒蛇enum.Flag
或enum.Enum
。
更准确地说,我想将一个参数传递给一个包含 enum.Flags 位组合的函数。而且我想避免为我想传递给函数的每个设置标志编写 module.TheFlags.flagX
。标志应替换布尔参数。
我想出了以下代码:
import enum
class AvailableFlags(enum.Flag):
flag1 = enum.auto()
flag2 = enum.auto()
class FuncFlags:
def __init__(self):
self._flags = AvailableFlags(0)
@property
def flag1(self):
self._flags |= AvailableFlags.flag1
return self
@property
def flag2(self):
self._flags |= AvailableFlags.flag2
return self
def __str__(self):
return str(self._flags.value)
def func(setup_flags: FuncFlags):
print(setup_flags)
if __name__ == "__main__":
func(FuncFlags().flag1)
func(FuncFlags().flag2)
func(FuncFlags().flag1.flag2)
func(FuncFlags())
它创建 FuncFlags 的实例,然后 误用 属性来设置返回更改对象本身的单个标志。
但是,人们会期望 属性 不会更改对象状态。
因此,尽管它有效,但这显然不是一个干净的解决方案。
所以,我的问题是,如何以一种干净、可重用的方式实现它?
我不是很清楚你想要完成什么,但也许这有帮助?
import enum
class AvailableFlags(enum.Flag):
flag1 = enum.auto()
flag2 = enum.auto()
flag1, flag2 = AvailableFlag
def func(setup_flags: AvailableFlags):
print(setup_flags)
if __name__ == "__main__":
func(flag1)
func(flag2)
func(flag1|flag2)
func()
与此同时,我通过添加另一层间接寻址找到了答案。
如果其他人感兴趣,我想在这里分享。
每次调用标志都会通过设置附加标志从当前实例创建一个新实例,从而维护对象状态。
如果我们尝试访问未定义的标志,则会引发异常(未显示)。
import enum
class AvailableFlags(enum.Flag):
flag1 = enum.auto()
flag2 = enum.auto()
class FlagHelper:
def __init__(self, cls, value = 0):
self._cls = cls
self._flags = self._cls(value)
def __getattr__(self, item):
if item in self._cls.__members__:
return self.__class__(self._flags | getattr(self._cls, item))
getattr(self._cls, item) # Let attribute error pass through
def __str__(self):
return str(self._flags.value)
class FuncFlags(FlagHelper):
def __init__(self, value = 0):
super().__init__(AvailableFlags, value)
def func(setup_flags: FuncFlags):
print(setup_flags)
if __name__ == "__main__":
ff = FuncFlags()
func(ff.flag1)
func(ff.flag2)
func(ff.flag1.flag2)
func(ff)
输出:
1
2
3
0
我想尽可能使用命名常量,而不是提供文字值或带有大量布尔参数的冗长函数签名。
因此我喜欢蟒蛇enum.Flag
或enum.Enum
。
更准确地说,我想将一个参数传递给一个包含 enum.Flags 位组合的函数。而且我想避免为我想传递给函数的每个设置标志编写 module.TheFlags.flagX
。标志应替换布尔参数。
我想出了以下代码:
import enum
class AvailableFlags(enum.Flag):
flag1 = enum.auto()
flag2 = enum.auto()
class FuncFlags:
def __init__(self):
self._flags = AvailableFlags(0)
@property
def flag1(self):
self._flags |= AvailableFlags.flag1
return self
@property
def flag2(self):
self._flags |= AvailableFlags.flag2
return self
def __str__(self):
return str(self._flags.value)
def func(setup_flags: FuncFlags):
print(setup_flags)
if __name__ == "__main__":
func(FuncFlags().flag1)
func(FuncFlags().flag2)
func(FuncFlags().flag1.flag2)
func(FuncFlags())
它创建 FuncFlags 的实例,然后 误用 属性来设置返回更改对象本身的单个标志。 但是,人们会期望 属性 不会更改对象状态。 因此,尽管它有效,但这显然不是一个干净的解决方案。
所以,我的问题是,如何以一种干净、可重用的方式实现它?
我不是很清楚你想要完成什么,但也许这有帮助?
import enum
class AvailableFlags(enum.Flag):
flag1 = enum.auto()
flag2 = enum.auto()
flag1, flag2 = AvailableFlag
def func(setup_flags: AvailableFlags):
print(setup_flags)
if __name__ == "__main__":
func(flag1)
func(flag2)
func(flag1|flag2)
func()
与此同时,我通过添加另一层间接寻址找到了答案。 如果其他人感兴趣,我想在这里分享。 每次调用标志都会通过设置附加标志从当前实例创建一个新实例,从而维护对象状态。 如果我们尝试访问未定义的标志,则会引发异常(未显示)。
import enum
class AvailableFlags(enum.Flag):
flag1 = enum.auto()
flag2 = enum.auto()
class FlagHelper:
def __init__(self, cls, value = 0):
self._cls = cls
self._flags = self._cls(value)
def __getattr__(self, item):
if item in self._cls.__members__:
return self.__class__(self._flags | getattr(self._cls, item))
getattr(self._cls, item) # Let attribute error pass through
def __str__(self):
return str(self._flags.value)
class FuncFlags(FlagHelper):
def __init__(self, value = 0):
super().__init__(AvailableFlags, value)
def func(setup_flags: FuncFlags):
print(setup_flags)
if __name__ == "__main__":
ff = FuncFlags()
func(ff.flag1)
func(ff.flag2)
func(ff.flag1.flag2)
func(ff)
输出:
1
2
3
0