在枚举构造中使用super()时出现名称错误

2024-09-29 06:30:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是python2.7.10和enum34库。我正努力做到以下几点:

from enum import Enum


class Foo(Enum):
    def __init__(self):
        pass


class Bar(Foo):
    VALUE = 1

    def __init__(self, value):
        super(Bar, self).__init__()

当这段代码运行时,我收到错误NameError: global name 'Bar' is not defined。有人能帮我解释一下为什么我会收到这个错误,以及是否可以调用枚举子类的父构造函数?提前谢谢你!在

编辑:Olivier Melançon的回溯(修订路径名):

^{pr2}$

Tags: fromimportselffooinitvaluedef错误
2条回答

问题是在Bar存在之前调用了Bar.VALUE.__init__。在

您可以在^{}中看到这种情况,但即使不查看代码,它也几乎可以通过来工作:Enum类的全部要点是,它的枚举成员是常量值,充当类的属性,同时也是它的实例。在

在这种情况下,这段代码将在3.4+中使用stdlib enum模块产生完全相同的错误,并在多个第三方enum替换中产生类似的错误。在

一般来说,如果你有枚举层次结构,你应该只把值放在“叶”类中,而行为只放在非叶类中。然而,在Restricted subclassing of enumerations中明确记录的唯一限制是非叶类中没有值,因此从技术上讲,您尝试的操作应该是合法的,即使这是不寻常的,并且从未明确打算起作用。在


如果您使用的是python3,有一个非常简单的解决方法:只需使用super()而不是{},这并不重要,因为{}还不存在。在

在Python2中,由于这是不可行的,您需要手动模拟super。对于一般性而言,这意味着编写代码来遍历mro等等,但是由于包含两个或多个Enum类的多重继承无论如何都不起作用,所以只需对其进行静态硬编码就可以了:

def __init__(self, value):
    Foo.__init__(self)

或者,如果将设计更改为将所有行为都放在非叶类中,也可以这样做:

^{pr2}$

最有可能的是,无论你实际想要完成什么,都可以用一种更好的方式来完成,而不需要这些改变。但既然你的玩具例子不能完成任何事情,就没有什么可以展示的了。在

要解决名称Bar在创建其成员时尚未绑定到BarEnum的问题,请使用:

super(self.__class__, self).__init__()

(请注意,self.__class__已取代{})

相关问题 更多 >