Python 3 Enums with Function Values

The documentation says:

The rules for what is allowed are as follows: _sunder_ names (starting and ending with a single underscore) are reserved by enum and cannot be used; all other attributes defined within an enumeration will become members of this enumeration, with the exception of __dunder__ names and descriptors (methods are also descriptors).

A "method" is just a function defined inside a class body. It doesn't matter whether you define it with lambda or def. So your example is the same as:

class Color(Enum):
    def Red():
        print('In Red')
    def Blue():
        print('In Blue')

In other words, your purported enum values are actually methods, and so won't become members of the Enum.


You can also use functools.partial to trick the enum into not considering your function a method of Color:

from functools import partial
from enum import Enum

class Color(Enum):
    Red = partial(lambda: print('In Red'))
    Blue = partial(lambda: print('In Blue'))

With this you can access name and value as expected.

Color.Red
Out[17]: <Color.Red: functools.partial(<function Color.<lambda> at 0x7f84ad6303a0>)>
Color.Red.name
Out[18]: 'Red'
Color.Red.value()
In Red

You can override the __call__ method:

from enum import Enum, auto

class Color(Enum):
    red = auto()
    blue = auto()

    def __call__(self, *args, **kwargs):
        return f'<font color={self.name}>{args[0]}</font>'

Can then be used:

>>> Color.red('flowers')
<font color=red>flowers</font>

If someone need/want to use Enum with functions as values, its possible to do so by using a callable object as a proxy, something like this:

class FunctionProxy:
    """Allow to mask a function as an Object."""
    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        return self.function(*args, **kwargs)

A simple test:

from enum import Enum
class Functions(Enum):
    Print_Function = FunctionProxy(lambda *a: print(*a))
    Split_Function = FunctionProxy(lambda s, d='.': s.split(d))

Functions.Print_Function.value('Hello World!')
# Hello World!
Functions.Split_Function.value('Hello.World.!')
# ['Hello', 'World', '!']