Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何定义作为函数的枚举值?_Python_Function_Enums - Fatal编程技术网

Python 如何定义作为函数的枚举值?

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

在这种情况下,我需要强制并向用户提供多个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 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)