我正在使用 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
。有人可以帮助解释为什么我收到此错误以及是否可以调用枚举子类的父构造函数?提前致谢!
编辑:Olivier Melanç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
最佳答案
问题是 Bar.VALUE.__init__
在 Bar
存在之前被调用。
您可以在 EnumMeta.__new__
中看到发生这种情况的位置,但即使不看代码,它也几乎必须以这种方式工作:Enum
类的全部要点在于它的枚举成员是常量值,充当类的属性,同时也是类的实例。
因此,此代码将在 3.4+ 中产生与 stdlib enum
模块完全相同的错误,以及与多个第三方 enum
替换的类似错误。
一般来说,如果您有 Enum 层次结构,您应该只将值放在“叶”类中,而只将行为放在非叶类中。但是,Restricted subclassing of enumerations 中实际明确记录的唯一限制。在非叶类中没有值,因此从技术上讲,您尝试做的事情应该是合法的,即使它不寻常并且从未明确打算工作。
如果您使用的是 Python 3,则有一个非常简单的解决方法:只需使用 super()
而不是 super(Bar, self)
,这并不重要Bar
还不存在。
在 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
最有可能的是,无论您实际尝试完成什么,都可以以更好的方式完成,而无需进行任何这些更改。但是由于您的玩具示例没有完成任何事情,因此没有更多内容可以展示。
关于python - 在枚举构造函数中使用 super() 时出现 NameError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51033366/