A class Message
extends Enum
to add some logic. The two important parameters are verbose level and message string, with other optional messages (*args
). Another class MessageError
is a special form of the Message
class in which verbose level is always zero, everything else is the same.
The following code screams TypeError
:
TypeError: Enum.new() takes 2 positional arguments but 3 were given
from enum import Enum
class Message(Enum):
verbose: int
messages: list[str]
def __new__(cls, verbose: int, message: str, *args):
self = object.__new__(cls)
self._value_ = message
return self
def __init__(self, verbose: int, message: str, *args):
self.verbose = verbose
self.messages = [self.value] + list(args)
class MessageError(Message):
def __new__(cls, message: str):
return super().__new__(cls, 0, message) # <- problem is here!
def __init__(self, message: str):
return super().__init__(0, message)
class Info(Message):
I_001 = 2, 'This is an info'
class Error(MessageError):
E_001 = 'This is an error'
I was expecting that super().__new__(cls, 0, message)
would call __new__
from the Message
class, but it seems that is not the case. What am I doing wrong here?
Enum
s are unusual (aka weird) in several regards, with creation being the biggest area. During enum class creation, after the members themselves have been created but before the class is returned, any existing __new__
is renamed to __new_member__
1 and the __new__
from Enum
itself is inserted into the class -- this is so calls like Info('This is an error')
will return the existing member (or raise), and not create a new member.
Your MessageError.__new__
should look like:
def __new__(cls, message: str):
return super().__new_member__(cls, 0, message)
1 In 3.11+ it's also saved as _new_member_
to follow the pattern of sunder names for enum-specific methods and attributes.
Disclosure: I am the author of the Python stdlib Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) library.