2012-07-28 84 views
3

我在學習Python,我發現了一些關於Python如何構造一個讓我困惑的子類。Python的繼承和__init__

我有一個繼承自列表類的類,如下所示。

class foo(list): 
    def __init__(self, a_bar): 
     list.__init__([]) 
     self.bar = a_bar 

我知道list.__init__([])需要在那裏,但我很困惑。在我看來,這行只會創建一個新的列表對象,然後將它分配給任何東西,所以我會懷疑它只會收集垃圾。 Python如何知道這個列表是我的對象的一部分?我懷疑幕後發生了一些事情,我想知道它是什麼。

+3

你從哪裏找到這段代碼?這是不正確的 – 2012-07-28 18:27:35

回答

0

實際對象不是用__init__創建的,而是用__new__創建的。 __init__不是用於創建對象本身,而是用於初始化它 - 也就是添加屬性等。在調用__init__時,__new__已被調用,因此在您的示例中,該列表在您的代碼運行之前已經創建。 __init__不應該返回任何東西,因爲它應該初始化「in-place」對象(通過改變它),所以它通過副作用起作用。 (見a previous questionthe documentation。)

2

你通常繼承和重寫__init__()功能時做到這一點:

list.__init__(self) 

如果你使用Python 3,你可以使用super()

super().__init__() 
3

執行多重繼承安全的方法是:

class foo(list): 
    def __init__(self, a_bar): 
     super(foo, self).__init__() 
     ... 

這可能會讓你更清楚地知道你正在調用基類ctor。

+0

它需要多一點MI安全。 – delnan 2012-07-28 18:29:09

+0

@delnan如..? – thebjorn 2012-07-28 18:31:16

+3

如繼承樹中的所有類同意'__init__'參數使用'super'。看[Python的super()被認爲是超級!](http://rhettinger.wordpress。COM/2011/5月26日/超認爲超/)。 – delnan 2012-07-28 18:52:54

1

你是有一定道理:

list.__init__([]) 

「創建一個新的列表對象。」但是這個代碼是錯誤的。正確的代碼_should_be:

list.__init__(self) 

你需要它的原因有,因爲你從list有它自己的__init__()方法來初始化自己的地方(大概)確實重要繼承。當你定義自己的__init__()方法時,你實際上覆蓋了同名的繼承方法。爲了確保父類的__init__()代碼也被執行,您需要調用該父類的__init__()

有這樣做的幾種方法:

#explicitly calling the __init__() of a specific class 
#"list"--in this case 
list.__init__(self, *args, **kwargs)  

#a little more flexible. If you change the parent class, this doesn't need to change 
super(foo, self).__init__(*args, **kwargs) 

更多關於super()看到this question,對超級的陷阱指導,見this article

+0

這應該是正確的答案! – 2014-02-11 22:45:54