python之super()与__init__()

本文详细探讨了Python中的`super()`和`__init__()`的区别和用法。`__init__()`主要用于实例化对象,而`super()`则用于调用父类的方法,尤其在处理多重继承时,能避免重复调用和解决查找顺序问题。在新式类中,`super()`是推荐的使用方式,因为它遵循C3线性化算法,确保了正确的继承顺序。
摘要由CSDN通过智能技术生成

                                             super()与__init__()

 

一、概述

__init__()一般用来创建对象的实例变量,或一次性操作。super()用于调用父类的方法,可用来解决多重继承问题。

单继承中,super()和__init__()功能类似,主要区别:1)使用super()继承则不用显式引用基类,父类发生变化时,利于维护;2)super()只能用于新式类中,需要继承object对象。

而在多重继承时,会涉及继承顺序,直接用类名调用父类方法会涉及查找顺序、重复调用等问题。super()则是返回继承顺序的下一个类,而不是父类。

 

_init_ 几点说明:

  • 子类没有定义自己的初始化函数,父类的初始化函数会被默认调用;要实例化子类的对象,需要传入父类初始化函数对应的参数

  • 如果子类定义了自己的初始化函数,而在子类中没有显式调用父类的初始化函数,则父类的属性不会被初始化

  • 如果子类定义了自己的初始化函数,在子类中显示调用父类,子类和父类的属性都会被初始化

一般为了使用扩展父类的行为,最好显式调用父类的__init__方法。

 

二、super()与__init__()区别

1、单继承中super()和__init__()实现功能类似,super()不用显式引用基类

class Base(object):
    def __init__(self, name):
        self.name = name
        print("Base create")
​
    def func(self):
        print("base fun")
​
​
class childA(Base):
    def __init__(self):
        print("childA create")
        Base.__init__(self, "A")        # 父类名硬编码到子类中
​
    def funA(self):
        print("funA")
​
​
class childB(Base):
    def __init__(self):
        print("childB create")
        super(childB, self).__init__('B')    # super,将子类名和self传递进去
​
​
if __name__ == '__main__':
    A = childA()
    #A.func()
    B = childB()
运行结果:

 

2、super()只能用于新式类

首先说明新式类与经典类的定义:

经典类是默认没有派生自某个基类的,而新式类默认派生自object基类,Python3之后的版本就只承认新式类了。

经典类在类多重继承时,采用从左至右深度优先的匹配方法,可能会存在查询继承树中绕过后面的父类等问题,而新式类采用C3算法进行匹配的。如:

class D():
    def foo(self):
        print "class D"
​
class B(D):
    pass
​
class C(D):
    def foo(self):
        print "class C"
​
class A(B, C):
    pass
​
f = A()
f.foo()

经典类采用深度优先的匹配方法,输出class D。新式类采用C3算法(区别与广度优化),输出class C。

3、多重继承-super不是父类,而是继承顺序的下一个类

super()返回的不是父类,而是继承顺序的下一个类

class Base(object):

    def __init__(self):
        print("Base Create")
​
​
class childA(Base):
    def __init__(self):
        print("init A")
        # Base.__init__(self)
        super(childA, self).__init__()
        print("init A end")
​
​
class childB(Base):
    def __init__(self):
        print("init B")
        # Base.__init__(self)
        super(childB, self).__init__()
        print("init B end")
​
​
class childC(childA, childB):
    pass

运行结果:

super(childA, self)返回当前类的继承顺序中childA后的一个类childB;然后再执行childB().__init__(),这样顺序执行下去。执行顺序是A->B->Base。

如果把childA()中的 super(childA, self).__init__() 换成Base._init_(self),在执行时,继承childA后就会直接跳到Base类里,而略过了childB。

 

4、super()可以避免重复调用

如:childA继承Base,childB继承childA和Base,如果childB需要调用Base的__init__()方法时,就会导致__init__()被执行两次:

class Base(object):
    def __init__(self):
        print("Base create")
class childA(Base):
    def __init__(self):
        print("A create")
        Base.__init__(self)
        print("A create End")
class childB(childA, Base):
    def __init__(self):
        childA.__init__(self)
        Base.__init__(self)
运行结果:

 

super则可以解决此重复调用的问题:

class Base(object):
    def __init__(self):
        print("Base create")
class childA(Base):
    def __init__(self):
        print("A create")
        super(childA, self).__init__()
        print("A create End")
class childB(childA, Base):
    def __init__(self):
        super(childB, self).__init__()

运行结果:

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值