簡體   English   中英

在枚舉構造函數中使用super()時的NameError

[英]NameError when using super() in enum constructor

我使用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

問題是在Bar存在之前調用了Bar.VALUE.__init__

您可以在EnumMeta.__new__看到這種情況發生,但即使不查看代碼,它也必須以這種方式工作: Enum類的重點是它的枚舉成員是作為類的屬性的常量值同時也是它的實例。

在這種情況下,此代碼將使用stdlib enum模塊在3.4+中產生完全相同的錯誤,並在多個第三方enum替換中產生類似錯誤。

通常,如果您具有Enum層次結構,則應該僅將值放在“葉子”類中,並僅將行為放在非葉子類中。 但是,在枚舉的限制子類中實際明確記錄的唯一限制是非葉類中沒有值,因此從技術上講,您嘗試做的事情應該是合法的,即使它是不尋常的並且從未明確打算工作。


如果您使用的是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

最有可能的是,無論您實際想要完成什么,都可以以更好的方式完成,而無需進行任何這些更改。 但是,由於你的玩具示例沒有完成任何事情,所以沒有什么可以展示的了。

要解決名稱Bar在創建成員時尚未綁定到Bar Enum的問題,請使用:

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

(注意self.__class__取代了Bar

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM