2015-01-07 21 views
1

我想了解super()的工作原理。我明白它的作用,但我不明白幕後發生的事情的機制。有一兩件事我完全不明白之間的區別在於:super()在方法開始或結束時被調用有什麼區別?

class b(a): 
    def __init__(self, name, age): 
     self.name=name 
     self.age=age 
     super(b, self).__init__(name, age) 

和:

class b(a): 
    def __init__(self, name, age): 
     super(b, self).__init__(name, age) 
     self.name=name 
     self.age=age 

也許有在這兩個例子中沒有什麼區別,但我知道有其他情況下的位置super()重要。例如,這個Django方法我需要幫助,我被指示將super()移到if語句之上,而不是在底部。我想知道爲什麼這很重要。

class Mymodel(models.Model): 
    photo = models.ImageField(upload_to="...", blank=True) 

def save(self, *args, **kwargs): 
    image_resized = kwargs.pop('image_resized',False) 
    super(Mymodel, self).save(*args, **kwargs) 
    if self.photo and image_resized: 
     basewidth = 300 
     filename = self.get_source_filename() 
       image = Image.open(filename) 
     wpercent = (basewidth/float(image.size[0])) 
     hsize = int((float(image.size[1])*float(wpercent))) 
     img = image.resize((basewidth,hsize), PIL.Image.ANTIALIAS) 
     self.photo = img 
     self.save(image_resized = True) 
+3

想一想;如果你的代碼依賴於只在超類'__init__'中初始化的實例屬性呢?你越早打電話就越好。另外,這是'超級'。 – jonrsharpe

+0

儘管如此,有些情況下你想最後調用它。就像'__new__'一樣。 –

+2

它只是一個方法調用**,儘管只有一個方法可以在父類中找到。但是*當你調用它時與調用其他方法具有相同的影響。東西發生。如果你不叫它,那東西就不會發生。 –

回答

6

b(如果有的話)的兩個版本之間的區別完全取決於超類(a)的功能。讓我們只需要一個更簡單,更清晰的例子:

class a(object): 
    def __init__(self): 
     self.foo = 23 

class b1(a): 
    def __init__(self, name, age): 
     self.foo = 42 
     super(b, self).__init__() 

class b2(a): 
    def __init__(self, name, age): 
     super(b, self).__init__() 
     self.foo = 42 

b1第一臺foo至42 - 然後(在實踐中)調用a.__init__,其中重置相同的屬性到23所以,self.foo結束後被價值23 b1.__init__

b2第一(在實踐中)調用a.__init__,它設置foo 23 - 然後,它前進到相同的屬性重置爲42.所以,self.foo結束是值得42 b2.__init__後。

我發現這種情況更簡單和更清晰,因爲它歸結爲對同一事物的兩個不同值的賦值 - 所以非常直觀,第二個賦值覆蓋了第一個賦值的效果。因此,在子類執行自己的事情之前調用超類的__init__意味着子類可以覆蓋超類中完成的部分或全部設置;之後調用它意味着恰恰相反。

而完全相同的推理適用於初始化操作,它比簡單分配self屬性稍微微妙一點:它全部關於哪個類,子類或超類,可以調整或否決其他類所做的事情(儘可能多因爲兩次初始化都是重要的)。

在OOP中,希望子類「覆蓋」超類的情況比反過來更常見;因此,調用超類__init__的正常時間在子類的開始處是正確的 - 這更加地道。當需要更精細的效果時,稍後可以調用超類的__init__,但在那些「稍微不正常」的情況下,它通常會幫助讀者解釋代碼添加註釋,解釋正在做什麼以及爲什麼......

+0

非常有幫助。謝謝! – stephan

1

super().__init__()執行類,「這」(或從py自)從繼承的構造函數。因此,如果有修改繼承變量的操作或需要在繼承的類的構造函數中使用的變量,則必須先調用它。 否則,只要您不需要它,它何時被調用並不重要。雖然最好的做法是始終在構造函數的開頭調用它,所以你總是知道它被調用的地方(如果它需要的話)。

+2

'super'本身不會執行任何操作,只返回當前實例的父類中執行的任何方法。 – Kroltan

+1

對不起,自從使用python以來,它仍然有一段時間,但仍然想幫忙。我編輯以更好地反映Python語言。 – Theyouthis

+0

沒問題,我不是故意要冒犯。只是指出,所以人們不會感到困惑(「但是我看到一個堆棧溢出的答案,說'super'運行構造函數!」)。我的英語並不完美,我經常聽起來會非常苛刻。抱歉。 – Kroltan

相關問題