python的super(),到底发生了什么?

本问题已经有最佳答案,请猛点这里访问。

我在尝试理解当我们用Python实例化子类时创建了什么对象,例如:

1
2
3
4
5
6
7
8
9
10
11
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()调用父类的构造函数。初始化(make, model, year)"实例化我们的子类。因此,我们的类ElectricCar()只有一个对象。

2) super(),调用父类的构造函数,创建"Car"类的对象,然后通过"super()"调用这个对象的构造函数。init(制作、模型、年)"。因此,我们有两个对象:Car()类的一个对象和ElectiricCar类的一个对象,在我们的例子中,它们是相同的。

哪一个是正确的?如果两者都没有,那么请解释到底发生了什么:

1
 super().__init__(make, model, year)


__init__不是构造函数,而是初始化器。在调用__init__时,对象已经构建好(通过__new__)。因此,您只得到一个对象,但是它被初始化了两次——例如,ElectricCar.__init__可能决定在Car.__init__运行之后重新初始化self.model

当调用super()时,将在当前实例的上下文中查找适当的基类。基本上,super().__init__(make, model, year)可以在您的示例中重写为Car.__init__(self, make, model, year)

这就是为什么在python的早期版本中,调用实际上是super(ElectricCar, self)——它查找当前类的基类(ElectricCar)并使用当前实例(self),就好像它是该类的一个实例一样。

注意,初始化并不意味着准备对象,它意味着准备对象的状态。即使对象没有实现__init__,它也是完全可用的。

澄清一下:当您调用ElectricCar()时,实际执行的内容与此类似:

1
2
3
4
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__