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

Python's super() , what exactly happens?

我试图了解当我们在 Python 中实例化子 class 时创建了哪些对象,例如:

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 时,我们通过调用此 class 的构造函数来实例化 class ElectricCar,后者又调用父对象的构造函数。它是如何发生的?现在我有两个猜测:

1) super() 只是对父 class 的引用,所以我们通过 "super().init(make, model, year)" 实例化我们的子 class 来调用父的构造函数。结果,我们的 class ElectricCar().

只有 ONE 对象

2)super(),调用parent的构造函数,创建"Car"class的对象,然后我们调用这个对象的构造函数,通过"super().init(make, model, year)"。结果我们有 两个对象 :一个 class Car() 对象和一个 class ElectiricCar 对象,在我们的例子中它们是相同的.

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

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

__init__ 不是一个构造函数,它是一个 初始化器 。在 __init__ 被调用时,对象已经被构建(通过 __new__)。所以你只得到一个对象,但它被初始化了两次 - 例如,ElectricCar.__init__ 可能决定在 Car.__init__ 已经 运行.

之后重新初始化 self.model

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

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

请注意,初始化并不意味着准备对象,它意味着准备对象的状态。一个对象即使没有实现 __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__ 的调用只会 modify/initialize 该对象。它可以使用其他函数来执行此操作,例如 Car.__init__