2011-12-23 60 views
18

在閱讀OpenStack的代碼時,我遇到了這個問題。對象的__init __()方法在python中做什麼?

一個名爲'Service'的類繼承了基類'object',然後在Service的__init__()方法中調用了對象的__init__。相關代碼如下所示:

類定義:

class Service(object): 

和服務的init方法定義:

def __init__(self, host, binary, topic, manager, report_interval=None, 
      periodic_interval=None, *args, **kwargs): 

和服務的init超(以下簡稱「對象」在這裏)的調用:

super(Service, self).__init__(*args, **kwargs) 

我不明白,最後一次通話,object.__init__()什麼實際你呢? 任何人都可以幫忙嗎?

回答

14

簡短的回答是,對象初始化.__ __()方法什麼也不做,除了檢查,沒有論據中未獲通過。見the source瞭解詳情。

當呼籲服務的情況下,super()通話將委託給對象初始化.__ __()和什麼都不會發生。

但是,當在服務的子類的實例上調用時,事情變得更有趣。 super()調用可能會委託給對象以外的某個類,該類是實例的父級,但不是父級服務。有關這種工作原理以及爲什麼它有用的詳細信息,請參閱博文Python's Super Considered Super

下面的例子(有點做作)表示服務的一個子類如何可以導致超級呼叫在服務被引導到稱爲顏色另一個類:

class Service(object): 
    def __init__(self, host, binary, topic, manager, report_interval=None, 
      periodic_interval=None, *args, **kwargs): 
     print 'Initializing Service' 
     super(Service, self).__init__(*args, **kwargs) 

class Color(object): 
    def __init__(self, color='red', **kwargs): 
     print 'Initializing Color' 
     self.color = color 
     super(Color, self).__init__(**kwargs) 

class ColoredService(Service, Color): 
    def __init__(self, *args, **kwds): 
     print 'Initializing Colored Service' 
     super(ColoredService, self).__init__(*args, **kwds) 

c = ColoredService('host', 'bin', 'top', 'mgr', 'ivl', color='blue') 

在例如,初始化按以下順序發生:

  1. 初始化彩色服務
  2. 初始化服務
  3. 初始化顏色
  4. 初始化對象 - 什麼都不做,除了參數檢查
+2

參考文獻[Python's Super Considered Super](http://rhettinger.wordpress.com/2011/05/26/super-considered-super/)有很多幫助。謝謝! – 2011-12-23 09:42:09

+1

'ColoredService'構造函數允許例如'foo ='bar''被傳遞,但是最終會失敗,因爲TypeError:object .__ init __()不帶參數。那麼在'super'調用'Service'和'Color'類中傳遞'* args'和'** kwargs'有什麼意義?你的例子在沒有它們的情況下也可以工作(並且會更健壯)。 – ekhumoro 2011-12-23 14:38:30

+0

@ekhumoro該評論應針對OpenStack的作者。 ''args''部分來自他們的代碼,調用者必須尊重該簽名。我只是添加了* Color *和* ColoredService *以顯示MRO如何從* Service *鏈接到* Color *鏈接到* object *。 – 2011-12-23 18:09:22

3

super()並不總是返回父類的代理。取而代之,它返回的代理MRO中的下一個類。在單繼承中,MRO和繼承鏈之間沒有區別。在多重繼承中,MRO可能會導致在繼承鏈上產生一個類而不是其他的繼承鏈。

+0

但這裏沒有多重繼承,作爲服務直接從目標 – 2011-12-23 04:24:16

+0

@can繼承:但是繼承從「服務」? – 2011-12-23 05:01:46

+0

我讀過關於MRO的文章,並且我認爲,因爲Service直接從對象繼承,所以super()在這裏沒有歧義。 Whaterver從Service繼承並沒有什麼不同。 – 2011-12-23 06:05:38

1

object.__init__()實際上並沒有做任何事情,除非super()調用應該包含在內,即使一個類只有object作爲超類。

One big problem with 'super' is that it sounds like it will cause the superclass's copy of the method to be called. This is simply not the case, it causes the next method in the MRO to be called (...) People omit calls to super(...).init if the only superclass is 'object', as, after all, object.init doesn't do anything! However, this is very incorrect. Doing so will cause other classes' init methods to not be called.

http://fuhm.net/super-harmful/

+0

但請注意,如果通過'* args'和'** kwargs'傳遞任何內容(除非它使用python 2.5或更早的版本運行),則OP的示例代碼將失敗。 – ekhumoro 2011-12-23 03:20:23

+0

你可以用更多的細節解釋你的想法嗎? @ekhumoro – 2011-12-23 06:07:28

相關問題