覆盖扩展 Enum 的类的 __new__

Mar*_*lin 4 python enums overriding typeerror new-operator

Message扩展Enum以添加一些逻辑。两个重要的参数是详细级别和消息字符串,以及其他可选消息 ( *args)。另一个类MessageError是该类的一种特殊形式,Message其中详细级别始终为零,其他一切都相同。

下面的代码令人尖叫TypeError

类型错误:枚举。new () 需要 2 个位置参数,但已给出 3 个

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'
Run Code Online (Sandbox Code Playgroud)

我原以为班级里super().__new__(cls, 0, message)会打来电话,但事实似乎并非如此。我在这里做错了什么?__new__Message

Eth*_*man 8

Enum在很多方面都是不寻常的(又名奇怪的),其中创造是最大的领域。在枚举类创建期间,在创建成员本身之后但在返回类之前,任何现有成员都__new__将重命名为__new_member__1并将__new__fromEnum本身插入到类中 - 这就是调用 likeInfo('This is an error')将返回现有成员(或引发) ,而不创建新成员。

你的MessageError.__new__应该看起来像:

    def __new__(cls, message: str):
        return super().__new_member__(cls, 0, message)
Run Code Online (Sandbox Code Playgroud)

1在 3.11+ 中,它也被保存为_new_member_遵循枚举特定方法和属性的分解名称模式。


声明:我是Python stdlibEnumenum34backportAdvanced Enumeration ( aenum)库的作者。