How to apply @enum.nonmember?

853 views Asked by At

I was trying to come up with a use case for the new @enum.nonmember decorator in Python 3.11. The docs clearly mention it is a decorator meant to be applied to members. However, when I tried literally decorating a member directly:

import enum


class MyClass(enum.Enum):
    A = 1
    B = 2

    @enum.nonmember
    C = 3

this results in an error as:

Traceback (most recent call last):
  File "C:\Program Files\Python311\Lib\code.py", line 63, in runsource
    code = self.compile(source, filename, symbol)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\codeop.py", line 153, in __call__
    return _maybe_compile(self.compiler, source, filename, symbol)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\codeop.py", line 73, in _maybe_compile
    return compiler(source, filename, symbol)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\codeop.py", line 118, in __call__
    codeob = compile(source, filename, symbol, self.flags, True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<input>", line 9
    C = 3
    ^
SyntaxError: invalid syntax

However, if I had declared an atribute as a property or a descriptor it also wouldn't become an Enum member... So how, when and why do you use @enum.nonmember?

1

There are 1 answers

3
Jasmijn On BEST ANSWER

You would use it like so:

import enum


class MyClass(enum.Enum):
    A = 1
    B = 2

    C = enum.nonmember(3)

As far as I can tell, the only reason why it is called a decorator, is because of nested classes.

Currently,

class MyClass(enum.Enum):
    A = 1
    B = 2

    class MyNestedClass:
        pass

makes MyClass.MyNestedClass into one of the members of MyClass. This will change in 3.13. So if you want the new behaviour now, you can use:

class MyClass(enum.Enum):
    A = 1
    B = 2

    @enum.nonmember
    class MyNestedClass:
        pass

In 3.13, if you want the current behaviour of making nested classes members, you can use

class MyClass(enum.Enum):
    A = 1
    B = 2

    @enum.member
    class MyNestedClass:
        pass

There is no reason to use enum.nonmember as a decorator on a method, since methods are already excluded from being members, but I think you could use enum.member on one to be able to define a method member if you wanted. Not sure why you would, though.