2016-07-04 67 views
2

我想明白,當我們在Python中實例的子類,例如創建什麼樣的對象:通過調用這個類的構造函數Python的超級(),究竟發生了什麼?

class Car(): 
    def __init__(self, make, model, year): 
     self.make = make 
     self.model = model 
     self.year = year 

class ElectricCar(Car): 
    def __init__(self, make, model, year): 
      super().__init__(make, model, year) 

my_tesla = ElectricCar('tesla', 'model s', 2016) 

當我們創建對象my_tesla,我們實例化類ElectricCar,它依次調用父項的構造函數。它是如何發生的?現在我有兩個猜測:

1)super()只是對父類的引用,所以我們通過「super()」調用父類的構造函數init(make,model,year)「實例化我們的子類。因此,我們只有我們類ElectricCar()的一個對象。 2)super(),調用父類的構造函數,創建「Car」類的對象,然後通過「super()」調用該對象的構造函數。年)」。因此,我們有兩個對象:類Car()的一個對象和ElectiricCar類的一個對象,在我們的例子中它們是相同的。

哪一個是正確的? 如果沒有,那麼請解釋一下到底發生了什麼的:

super().__init__(make, model, year) 
+3

沒有。你仍然只有一個物體,一個'ElectricCar'。構造函數與其他任何函數一樣。它不會爲你「創建」一個對象 - 在執行構造函數時,該對象已經由底層運行時創建。構造函數只是在那裏初始化那個新的對象。所以調用super().__ init__只是運行一個普通的對象方法。該方法是構造函數的事實是無關緊要的。只有當它由對象構建器自動執行時纔是構造器。 –

+1

http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods – jbat100

回答

3

__init__不是構造函數,這是一個初始化。在調用__init__時,對象已經被構建(通過__new__)。因此,您只能獲得一個對象,但已初始化兩次 - 例如,在運行Car.__init__之後,ElectricCar.__init__可能會決定重新初始化self.model

當調用super()時,在當前實例的上下文中查找適當的基類。基本上,在你的例子中,super().__init__(make, model, year)可以改寫爲Car.__init__(self, make, model, year)

這就是爲什麼在早期版本的Python,電話竟是super(ElectricCar, self) - 它查找當前類(ElectricCar)的基類,並使用當前實例(self),就好像它是這個類的一個實例來代替。

請注意,初始化並不意味着準備對象,它意味着準備對象的狀態。一個對象即使在不執行__init__時也是完全有效的。


澄清:當你打電話ElectricCar(),什麼是真正執行接近這樣的:

that_object = ElectricCar.__new__() # this will actually use object.__new__ 
if isinstance(that_object, ElectricCar): 
    ElectricCar.__init__(that_object) 
return that_object 

這意味着你必須從調用ElectricCar.__new__一個對象。撥打ElectricCar.__init__只會修改/初始化該對象。它可以使用其他功能,例如Car.__init__

+0

所以,這兩個類的對象是在任何情況下創建的?和: super().__ init __(make,model,year) 我們只是初始化我們的ElectricCar對象?因此,我們有一個Car類的一個對象未​​初始化,並且ElectricCar類的一個對象已初始化? –

+0

只有*一個*對象被創建,即當您調用'ElectricCar()'時。 *該對象然後被用作'that_object .__ init __()',它解析爲'ElectricCar .__ init __(self = that_object)',它使用super調用'Car .__ init __(self = that_object)'。 – MisterMiyagi