Python 如何定义作为函数的枚举值?
在这种情况下,我需要强制并向用户提供多个select函数中的一个选项,以作为参数传递给另一个函数: 我真的很想实现以下目标:Python 如何定义作为函数的枚举值?,python,function,enums,Python,Function,Enums,在这种情况下,我需要强制并向用户提供多个select函数中的一个选项,以作为参数传递给另一个函数: 我真的很想实现以下目标: from enum import Enum #Trivial Function 1 def functionA(): pass #Trivial Function 2 def functionB(): pass #This is not allowed (as far as i can tell the values should be intege
from enum import Enum
#Trivial Function 1
def functionA():
pass
#Trivial Function 2
def functionB():
pass
#This is not allowed (as far as i can tell the values should be integers)
#But pseudocode for what I am after
class AvailableFunctions(Enum):
OptionA = functionA
OptionB = functionB
因此,可以执行以下操作:
def myUserFunction(theFunction = AvailableFunctions.OptionA):
#Type Check
assert isinstance(theFunction,AvailableFunctions)
#Execute the actual function held as value in the enum or equivalent
return theFunction.value()
你的假设是错误的。值可以是任意的,它们不限于整数。发件人: 上面的示例使用整数作为枚举值。使用整数 简洁方便(默认情况下由函数API提供), 但没有严格执行。在绝大多数用例中,一个 不关心枚举的实际值是什么但是如果 值很重要,枚举可以有任意值。 然而,函数的问题是它们被认为是方法定义而不是属性
In [1]: from enum import Enum
In [2]: def f(self, *args):
...: pass
...:
In [3]: class MyEnum(Enum):
...: a = f
...: def b(self, *args):
...: print(self, args)
...:
In [4]: list(MyEnum) # it has no values
Out[4]: []
In [5]: MyEnum.a
Out[5]: <function __main__.f>
In [6]: MyEnum.b
Out[6]: <function __main__.MyEnum.b>
样本运行:
In [7]: from functools import partial
In [8]: class MyEnum2(Enum):
...: a = partial(f)
...: def b(self, *args):
...: print(self, args)
...:
In [9]: list(MyEnum2)
Out[9]: [<MyEnum2.a: functools.partial(<function f at 0x7f4130f9aae8>)>]
In [10]: MyEnum2.a
Out[10]: <MyEnum2.a: functools.partial(<function f at 0x7f4130f9aae8>)>
除了…的答案之外。。。如果使用上述包装器方法,则会丢失有关原始函数的信息,如
\uuuuu name\uuuuuu
,\uuuu repr\uuuu
等包装好之后。例如,如果要使用sphinx生成源代码文档,这将导致问题。因此,将以下内容添加到包装器类中
类包装器:
定义初始化(自身,功能):
自我功能
functools.update_包装(self,function)
定义调用(self,*args,**kwargs):
返回self.function(*args,**kwargs)
定义报告(自我):
返回self.function.\uuu repr\uuuu()
基于的方法,我只想强调,我们也可以使用多个函数的字典作为值,并具有更广泛的多态性,类似于Java中的枚举。下面是一个虚构的例子来说明我的意思:
from enum import Enum, unique
@unique
class MyEnum(Enum):
test = {'execute': lambda o: o.test()}
prod = {'execute': lambda o: o.prod()}
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
elif not name.startswith("_"):
value = self.__dict__['_value_']
return value[name]
raise AttributeError(name)
class Executor:
def __init__(self, mode: MyEnum):
self.mode = mode
def test(self):
print('test run')
def prod(self):
print('prod run')
def execute(self):
self.mode.execute(self)
Executor(MyEnum.test).execute()
Executor(MyEnum.prod).execute()
显然,当只有一个函数时,字典方法没有提供额外的好处,所以当有多个函数时,使用这种方法。确保键在所有值上都是一致的,否则,使用将不会是多态的
\uu getattr\uuu
方法是可选的,它只用于语法糖(即,如果没有它,mode.execute()
将变成mode.value['execute']()
)
因为字典不能成为只读的,所以使用namedtuple
会更好,只需要对上面的内容做一些小的修改
from enum import Enum, unique
from collections import namedtuple
EnumType = namedtuple("EnumType", "execute")
@unique
class MyEnum(Enum):
test = EnumType(lambda o: o.test())
prod = EnumType(lambda o: o.prod())
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
elif not name.startswith("_"):
value = self.__dict__['_value_']
return getattr(value, name)
raise AttributeError(name)
另一种选择:将函数放在dict中,以函数名为键。您发现了Enum的边缘情况……当python构建一个类时,它会将函数属性添加为该类的方法。这就是为什么它们不会最终成为
Enum
的值。正如我在回答中所示,很容易“愚弄”它请注意,\uuu call\uuu
方法应该包含一个return
语句,否则当您调用函数时,您将不会得到预期的响应。我被困在那里2个小时。事后看来,这似乎很明显,但如果其他人被困在这里…@Logister,只有在函数让我们返回一个值。无需导入staticmethod
,顺便说一句,您只需执行a=staticmethod(f)
即可。@mar77i没错。我编辑了答案以显示该选项。谢谢。我没有让staticmethod
工作,但是,functools.partial
工作得很好。感谢您提供了这个聪明的解决方案!
In [1]: from enum import Enum
In [2]: def f(*args):
...: print(args)
...:
In [3]: class MyEnum(Enum):
...: a = partial(f)
...: def __call__(self, *args):
...: self.value(*args)
...:
In [5]: MyEnum.a(1,2,3) # no need for MyEnum.a.value(1,2,3)
(1, 2, 3)
from enum import Enum, unique
@unique
class MyEnum(Enum):
test = {'execute': lambda o: o.test()}
prod = {'execute': lambda o: o.prod()}
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
elif not name.startswith("_"):
value = self.__dict__['_value_']
return value[name]
raise AttributeError(name)
class Executor:
def __init__(self, mode: MyEnum):
self.mode = mode
def test(self):
print('test run')
def prod(self):
print('prod run')
def execute(self):
self.mode.execute(self)
Executor(MyEnum.test).execute()
Executor(MyEnum.prod).execute()
from enum import Enum, unique
from collections import namedtuple
EnumType = namedtuple("EnumType", "execute")
@unique
class MyEnum(Enum):
test = EnumType(lambda o: o.test())
prod = EnumType(lambda o: o.prod())
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
elif not name.startswith("_"):
value = self.__dict__['_value_']
return getattr(value, name)
raise AttributeError(name)