5

How can I define a Python enum class that somehow derives from int, has a custom starting value, and adds custom attributes? I know how to derive from int using enum.IntEnum and set the starting value,

Goo = enum.IntEnum("Goo", "MOO FOO LOO", start = 42)

and how to add custom attributes to the base enum type,

class Goo(enum.Enum):
    MOO = (42, "forty-two")
    FOO = (43, "forty-three")
    LOO = (44, "forty-four")

    def __init__(self, value, alias):
        self._value = value   #self.value gives AttributeError, as expected, grrr...
        self.alias = alias

but how do I do all three? I've tried all manner of __new__() too,

class Goo(int, enum.Enum):
    MOO = (42, "forty-two")
    FOO = (43, "forty-three")
    LOO = (44, "forty-four")

    def __new__(cls, value, alias):
        self = super().__new__(cls, value)
        self.alias = alias

        return self

mostly with odd errors,

TypeError: int() takes at most 2 arguments (3 given)

in this case. Thanks.

Jim

1 Answer 1

5

The behavior you want isn't already available in the stdlib Enum. You could use itertools.count() to get the numbers:

from enum import IntEnum
from itertools import count

_goo_count = count(42)
class Goo(IntEnum):
    #
    MOO = "forty-two"
    FOO = "forty-three"
    LOO = "forty-four"
    #
    def __new__(cls, alias):
        value = next(_goo_count)
        member = int.__new__(cls, value)
        member._value_ = value
        member.alias = alias
        return member

or you can use aenum:

from aenum import IntEnum

class Goo(IntEnum):
    _start_ = 42
    _init_ = 'alias'
    #
    MOO = "forty-two"
    FOO = "forty-three"
    LOO = "forty-four"

either way, in use it looks like:

>>> Goo.MOO
<Goo.MOO: 42>

>>> Goo.MOO.alias
'forty-two'

>>> Goo.MOO == 42
True

A couple stylistic notes:

  • you don't need parentheses to define a tuple

    • except for an empty tuple
    • or some place (like a function call), where the command would be interpreted as not a tuple
  • white space is good ;-)


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

Sign up to request clarification or add additional context in comments.

3 Comments

Mine does have a __new__(), and not an __init__(). The only real difference is that I called super().__new__(), and you called int.__new__(). That gets rid of the error, but still doesn't let me specify a starting value. I'd rather avoid listing the value of every enum, as I'm able to do in my first example. Thanks for the reply.
You also named the integer _value_. I didn't, but it's required by the metaclass.
@Jim: Redid answer to get all three points: derives from int, has custom starting value, and has custom attributes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.