我希望尽可能使用命名常量,而不是提供带有大量布尔参数的文字值或较长的函数签名。
所以我喜欢python的enum.Flag
或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