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__
。
我试图了解当我们在 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__
。