Functions as Enum member values
Peter Otten
__peter__ at web.de
Mon May 31 13:24:23 EDT 2021
On 31/05/2021 17:57, Colin McPhail via Python-list wrote:
> Hi,
>
> According to the enum module's documentation an Enum-based enumeration's members can have values of any type:
>
> "Member values can be anything: int, str, etc.."
You didn't read the fineprint ;)
"""
The rules for what is allowed are as follows: names that start and end
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 special methods (__str__(),
__add__(), etc.), descriptors (methods are also descriptors), and
variable names listed in _ignore_
""""
Functions written in Python are descriptors and therefore cannot be
used. Builtin functions aren't, leading to the following somewhat
surprising difference:
>>> def foo(self): print("foo")
>>> class A(Enum):
x = foo # foo.__get__ exists -> foo is a descriptor
# the enum library assumes you are adding a
# method to your
# class, not an enumeration value.
y = sum # no sum.__get__ attribute -> function
# treated as an enumeration value.
>>> list(A)
[<A.y: <built-in function sum>>]
>>> A.x
<function foo at 0x012096A0>
>>> A.y
<A.y: <built-in function sum>>
>>> A.y.x()
foo
> I defined one with functions as member values. This seemed to work as long as the functions were defined ahead of the enumeration's definition. However I then noticed that my enumeration class was a bit weird: even although I could reference the enumeration's members individually by name I couldn't iterate through the members in the normal fashion - it seemed to have no members. Also, calling type() on a member gave the result <class 'function'> instead of the expected <enum 'enum name'>.
>
> I am using Python 3.9.5 from python.org on macOS 11.4. Below is a small test script and its output. Are my expectations wrong or is there a problem with Enum?
>
> Regards,
> Colin
>
> -------------------------------
> from enum import Enum
>
> def connect_impl():
> print("message from connect_impl()")
>
> def help_impl():
> print("message from help_impl()")
>
> class Command1(Enum):
> CONNECT = 1
> HELP = 2
>
> class Command2(Enum):
> CONNECT = connect_impl
> HELP = help_impl
>
> if __name__ == "__main__":
>
> def print_enum(cls, mbr):
> print(f"{cls.__name__}\n type(): {type(Command1)}")
> print(f" type of enum member: {type(mbr)}")
> print(f" number of members: {len(cls)}")
> print(" enum members:")
> if len(cls) > 0:
> for c in cls:
> print(f" {c}")
> else:
> print(" <none>")
> print(f" dir(): {dir(cls)}")
>
> member_1 = Command1.HELP
> print_enum(Command1, member_1)
> print()
>
> member_2 = Command2.HELP
> print_enum(Command2, member_2)
> print()
> print("call Command2 member: ", end="")
> member_2()
> print()
>
> -------------------------------
> (qt6) % python3 try_enum.py
> Command1
> type(): <class 'enum.EnumMeta'>
> type of enum member: <enum 'Command1'>
> number of members: 2
> enum members:
> Command1.CONNECT
> Command1.HELP
> dir(): ['CONNECT', 'HELP', '__class__', '__doc__', '__members__', '__module__']
>
> Command2
> type(): <class 'enum.EnumMeta'>
> type of enum member: <class 'function'>
> number of members: 0
> enum members:
> <none>
> dir(): ['__class__', '__doc__', '__members__', '__module__']
>
> call Command2 member: message from help_impl()
>
> (qt6) %
> -------------------------------
>
More information about the Python-list
mailing list