2016-07-04 69 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