Python Forum

Full Version: Having trouble writing an Enum with a custom __new__ method
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have an enum subclass where I need to associate two pieces of data with each enum. The first is used for the enum value itself, the second needs to be stored as an attribute.

Here is an example showing what I am trying to do:

from enum import Enum
class MyEnum(Enum):
    MEMBER = ("This is my enum", 1.5)
    def __new__(cls, value, extra):
        obj = super().__new__(cls, value)
        obj._value_ = value
        obj.extra = extra
        return obj
What I expect to get is this:

MyEnum.MEMBER.value == "This is my enum"  # This should return True
MyEnum.MEMBER.extra == 1.5  # This should return True
But instead, I get this error:

Error:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.10/enum.py", line 288, in __new__ enum_member = __new__(enum_class, *args) File "<stdin>", line 4, in __new__ File "/usr/local/lib/python3.10/enum.py", line 701, in __new__ raise ve_exc ValueError: 'This is my enum' is not a valid MyEnum
What is the right way to override __new__ in an Enum?

I have read the docs, but they only show an example where you are subclassing another class as well as Enum:

https://docs.python.org/3/library/enum.h...ew-vs-init
From the docs you referenced:
Output:
When to use __new__() vs. __init__() __new__() must be used whenever you want to customize the actual value of the Enum member. Any other modifications may go in either __new__() or __init__(), with __init__() being preferred.
In other words use __new__ when you want to an enum that has a different type of value. Their example used bytes. Your value is a str.
class MyEnum(str, Enum):
    def __new__(cls, value, extra):
        obj = str.__new__(cls, [value])
        obj._value_ = value
        obj.extra = extra
        return obj

    MEMBER = ("This is my enum", 1.5)

print(MyEnum.MEMBER)
print(MyEnum.MEMBER.value)
print(MyEnum.MEMBER.extra)
Output:
MyEnum.MEMBER This is my enum 1.5
You were trying to create a new enum whose value was your new enum class.
Thanks deanhystad, but my enums shouldn't be a string subclass.
I think I have found a solution thanks to this blog post.

from enum import Enum

class MyEnum(Enum):
	MEMBER = ("Hello world", 1.5)
	def __new__(cls, value, extra):
		obj = object.__new__(cls)  # Don't use super(), use object
		obj._value_ = value
		obj.extra = extra
		return obj
Why not? Their value is a string. If I want an enum that has integer values I used use an IntEnum.