在枚举构造函数中使用super()时出现NameError

时间:2018-06-26 00:23:25

标签: python python-2.7 enums super nameerror

我正在将Python 2.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。有人可以帮助解释为什么我收到此错误,以及是否可以调用枚举子类的父构造函数吗?预先谢谢你!

编辑:OlivierMelançon的回溯(已删除路径名):

Traceback (most recent call last):
  File "/.../test.py", line 9, in <module>
    class Bar(Foo):
  File "/.../lib/python2.7/site-packages/enum/__init__.py", line 236, in __new__
    enum_member.__init__(*args)
  File "/.../test.py", line 13, in __init__
    super(Bar, self).__init__()
NameError: global name 'Bar' is not defined

Process finished with exit code 1

2 个答案:

答案 0 :(得分:1)

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

您可以在EnumMeta.__new__中看到这种情况的发生,但是即使不看代码,也可以 这样工作:Enum的全部意义class是它的枚举成员是常量值,既充当该类的属性,又充当它的实例。

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

通常,如果您完全具有Enum层次结构,则应仅将值放在“叶子”类中,而将行为仅放在非叶子类中。但是,实际上在Restricted subclassing of enumerations中明确记录的唯一限制是非叶子类中没有值,因此从技术上讲,您试图做的事情应该是合法的,即使它很不寻常且从未明确打算起作用。 / p>


如果您使用的是Python 3,则有一个非常简单的解决方法:仅使用super()而不是super(Bar, self),这与Bar还不存在无关。< / p>

在Python 2中,由于该操作不可行,因此您需要手动模拟super。出于全面考虑,这意味着编写代码来遍历mro,依此类推,但是由于包括两个或多个Enum类的多重继承仍然无法正常工作,因此只需硬编码就可以了它是静态的:

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

或者,如果您更改设计以将所有行为放在非叶子类中,那么这也将起作用:

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

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

class Baz(Bar):
    VALUE = 1

最有可能的是,您实际上想要完成的任何事情都可以以更好的方式完成,而无需进行任何更改。但是,由于您的玩具示例无法完成任何事情,因此没有更多可显示的内容。

答案 1 :(得分:0)

要解决创建成员时名称copy /b "path\7zS2.sfx" + "path\config.txt" + "pathTo\fileName.7z" outputName.exe 尚未绑定到Bar Bar的问题,请使用:

Enum

(请注意,super(self.__class__, self).__init__() 取代了self.__class__