I noticed an oddity in the Python 3 Enums (link).
If you set the value of an Enum to a function, it prevents the attribute from being wrapped as an Enum object, which prevents you from being able to use the cool features like EnumCls['AttrName']
to dynamically load the attribute.
Is this a bug? Done on purpose?
I searched for a while but found no mention of restricted values that you can use in an Enum.
Here is sample code that displays the issue:
class Color(Enum):
Red = lambda: print('In Red')
Blue = lambda: print('In Blue')
print(Color.Red) # <function> - should be Color.Red via Docs
print(Color.Blue) # <function> - should be Color.Bluevia Docs
print(Color['Red']) # throws KeyError - should be Color.Red via Docs
Also, this is my first time asking, so let me know if there's anything I should be doing differently! And thanks for the help!
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>
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.
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', '!']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With