How to define enum values that are functions?

后端 未结 2 1561
名媛妹妹
名媛妹妹 2021-01-04 03:32

I have a situation where I need to enforce and give the user the option of one of a number of select functions, to be passed in as an argument to another function:

I

2条回答
  •  被撕碎了的回忆
    2021-01-04 03:53

    Your assumption is wrong. Values can be arbitrary, they are not limited to integers. From the documentation:

    The examples above use integers for enumeration values. Using integers is short and handy (and provided by default by the Functional API), but not strictly enforced. In the vast majority of use-cases, one doesn’t care what the actual value of an enumeration is. But if the value is important, enumerations can have arbitrary values.

    However the issue with functions is that they are considered to be method definitions instead of attributes!

    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]: 
    
    In [6]: MyEnum.b
    Out[6]: 
    

    You can work around this by using a wrapper class or just functools.partial or (only in Python2) staticmethod:

    from functools import partial
    
    class MyEnum(Enum):
        OptionA = partial(functionA)
        OptionB = staticmethod(functionB)
    

    Sample run:

    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]: [)>]
    
    In [10]: MyEnum2.a
    Out[10]: )>
    

    Or using a wrapper class:

    In [13]: class Wrapper:
        ...:     def __init__(self, f):
        ...:         self.f = f
        ...:     def __call__(self, *args, **kwargs):
        ...:         return self.f(*args, **kwargs)
        ...:     
    
    In [14]: class MyEnum3(Enum):
        ...:     a = Wrapper(f)
        ...:     
    
    In [15]: list(MyEnum3)
    Out[15]: [>]
    

    Also note that if you want you can define the __call__ method in your enumeration class to make the values callable:

    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)
    

提交回复
热议问题