Python类继承中__init__方法的调用机制详解
本文深入解析Python类继承中__init__方法的实际调用行为。重点说明子类未显式声明__init__时如何调用父类初始化,以及显式声明后父类属性缺失的问题。同时探讨多继承场景下的MRO查找机制及super函数的使用特性,通过代码实例展示不同情况下的对象属性状态。
Python类继承机制概述
Python类的继承机制
许多关于Python类继承的文章往往侧重于介绍面向对象编程(OOP)、多态等抽象概念。对于已具备一定基础的开发者而言,这类理论阐述的实际帮助有限。相比之下,直接通过具体代码场景展示不同情况下的运行效果,更能直观地揭示代码行为,从而为开发者提供更具操作性的指导。以下将摒弃冗长的理论铺垫,直接通过代码示例进行说明。
本文的分析不区分经典类与新式类,所述结论同时适用于这两种类型的类定义。
__init__方法的调用规则与属性继承
在类中,__init__函数仅是一个用于初始化的方法。需要注意的是,初始化与实例创建并非同一过程:实例的创建实际上是通过一个内部的create机制完成的。如果子类中没有显式声明__init__函数,子类在实例化时将自动调用父类的__init__函数,但不会调用父类的父类(即祖父类)的__init__函数。反之,如果子类显式声明了__init__函数,则在子类初始化时不会调用父类的初始化函数,仅执行子类中声明的__init__。此时,子类实例中将不包含父类__init__函数中定义的属性。
具体示例如下:
class animal():
name="hh"
sex="man"
def __init__(self):
self.height=10
self.weight=50
def deception(self):
print "ansible.height:"+self.height+" animal.weight:"+self.weight
def run(self):
print "animal is running...."
class dog(animal):
def __init__(self):
pass
if __name__=="__main__":
dg=dog()
print dg.__dict__
运行上述代码的结果为:
{}
当将dog类修改为以下形式时(注意:此时未显式声明__init__方法):
class dog(animal):
def run(self):
print "dog is running..."
由于直接调用了父类animal的__init__方法,运行结果如下:
{'weight': 50, 'height': 10}
若此时存在一个类继承自dog类,将会发生什么情况?Python解释器的查找逻辑是:先在子类中寻找__init__方法,若未找到,则向父类查找,直至找到并运行为止。在此过程中,父类的父类的__init__方法不会被执行。因此,那些未被执行的__init__方法中所创建的属性在实例中是不存在的。例如,在前面的第一次运行示例中,得到的实例并没有weight和height属性。
class animal():
name="hh"
sex=""
def __init__(self):
self.height=10
self.weight=50
def deception(self):
print "ansible.height:"+self.height+" animal.weight:"+self.weight
def run(self):
print "animal is running...."
class dog(animal):
def __init__(self):
pass
def run(self):
print "dog is running..."
class jinmao(dog):
# def __init__(self):
# self.ji="jinmao"
pass
if __name__=="__main__":
dg=jinmao()
print dg.__dict__
此时的运行结果同样为:
{}
多继承中的初始化查找机制
在类的多继承场景中,会产生何种状况?在多继承中,Python会运行继承参数列表中第一个父类声明的__init__函数。如果该父类中没有__init__函数,则继续向上查找其父类,依此类推。如果遍历到根类仍未找到,则转而处理第二个参数声明的父类,过程与第一个参数相同,直到找到__init__函数为止。如果所有父类中均未找到__init__函数,则不进行初始化操作。读者可根据前述示例自行测试验证。
super函数的使用与特性
关于在子类中调用父类方法时super函数的使用及其特性。
总结:若希望深入了解Python虚拟机具体如何创建类(例如加载.pyc文件时,通过C语言逻辑将类对象放置到内存的具体过程),这仍是一个值得探索的领域。期待与读者共同深入研究。
感谢阅读,希望本文内容能对大家有所帮助,感谢各位对本站的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









