1

You can customise an enum so the members have extra attributes. There are plenty of examples of that to be found. They all look something like this:

class EnumWithAttrs(Enum):
    def __new__(cls, *args, **kwargs):
        value = len(cls.__members__) + 1
        obj = object.__new__(cls)
        obj._value_ = value
        return obj
    def __init__(self, a, b):
        self.a = a
        self.b = b
    
    GREEN = 'a', 'b'
    BLUE = 'c', 'd'

this example is from https://stackoverflow.com/a/19300424/6439229

The majority of the examples I found show __new__ to accept kwargs, but is it actually syntactically possible to pass kwargs to __new__?

This gives SyntaxErrors:

class EnumWithAttrs(Enum):
    GREEN = 'a', foo='b'
    BLUE = 'c', **{'bar':  'd'}

So does this functional syntax:

Color = EnumWithAttrs('Color', [('GREEN', 'a', foo='b'), ('BLUE', 'c', **{'bar': 'd'})])

Do people put the **kwargs in the function def of __new__ just out of habit, or is there really a way to use them?

EDIT: I'm not looking for a workaround to using kwargs, like passing a dict as a positional argument.

mahkitah
  • 562
  • 1
  • 6
  • 19

2 Answers2

1

Currently, there is no way to pass keyword args to an enum's __new__ or __init__, although there may be one in the future.

The third-party library aenum1 does allow such arguments using its custom auto.


1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
0

You could do

from enum import Enum


class EnumWithAttrs(Enum):
    def __new__(cls, *args, **kwargs):
        value = len(cls.__members__) + 1
        obj = object.__new__(cls)
        obj._value_ = value
        return obj

    def __init__(self, a, attrs):
        self.a = a
        self.attrs = attrs or {}


class AttributeyColor(EnumWithAttrs):
    GREEN = 'a', {'bar': 'b'}
    BLUE = 'c', {'glar': 'blarb'}


print(AttributeyColor.GREEN.attrs)

but this feels like abuse of Enums to me...

AKX
  • 152,115
  • 15
  • 115
  • 172
  • Off course you can pass a dict as a positional argument to achieve the same thing as using kwargs, but it doesn't answer the question. I'd like to know if the syntax exists to use kwargs. – mahkitah Apr 04 '23 at 12:24
  • The syntax is then `dict(bar="b", ...)`, there is no free-standing syntax for how keyword arguments are generally passed. – AKX Apr 04 '23 at 12:25