zoukankan      html  css  js  c++  java
  • python3 super().__init__() 和 __init__() 的区别

    1、单继承

    super().__int__()和 Base.__init__(self)是一样的, super()避免了基类的显式调用。

    class Base(object):
        def __init__(self):
            print('Create Base')
    
    class ChildClassA(Base):
        def __init__(self):
            print('Create ChildClassA')
            super().__init__()
    
    ChildClassA()
    #输出
    #Create ChildClassA
    #Create Base

    2、多继承

    注意:多继承时,会设计继承顺序,supper()相当于返回继承顺序的下一个类,而不是父类。

    def GetSupperOrder(class_name,self):
        mro = self.__class__.mro()
        # #mro()用来获得类的继承顺序。
        return mro[mro.index(class_name) + 1]
    
    class Base(object):
        def __init__(self):
            print('Create Base')
    
    class ChildClassA(Base):
        def __init__(self):
            print('Enter ChildClassA')
            super().__init__()
            print('Leave ChildClassA')
    
    class ChildClassB(Base):
        def __init__(self):
            print('Enter ChildClassB')
            super().__init__()
            print('Leave ChildClassB')
    
    class ChildClassC(ChildClassA,ChildClassB):
        pass
    
    c = ChildClassC()
    print(c.__class__.__mro__)
    # 输出:
    #Enter ChildClassA
    #Enter ChildClassB
    #Create Base
    #Leave ChildClassB
    #Leave ChildClassA
    #(<class '__main__.ChildClassC'>, <class '__main__.ChildClassA'>, <class '__main__.ChildClassB'>, <class '__main__.Base'>, <class 'object'>)

    从以上结果,可以看出:
    super()和父类没有关系,继承执行的顺序是 ChildClassA → ChildClassB → Base → Object

    执行过程:
    首先初始化ChlidClassC() ,初始化时先调用ChildClassA的构造方法__Init__(),
    进而调用super().__init__()方法,此方法返回当前类的继承顺序中ChildClassA后的一个类ChildClassB,然后在执行ChildClassB的构造方法,
    最后执行Base的构造方法,然后依次返回,并执行完成。

     在多重继承中 ,ChildClassA()中的 super().__init__() 换成Base.__init__(self),在执行时,继承childA后就会直接跳到Base类里,而略过了ChildClassB:

    Enter ChildClassA
    Create Base
    Leave ChildClassA
    (<class '__main__.ChildClassC'>, <class '__main__.ChildClassA'>, <class '__main__.ChildClassB'>, <class '__main__.Base'>, <class 'object'>)

    从super()方法可以看出,super()的第一个参数可以是继承链中任意一个类的名字,
      如果是本身就会依次继承下一个类;

      如果是继承链里之前的类便会无限递归下去;

      如果是继承链里之后的类便会忽略继承链汇总本身和传入类之间的类;

      比如将ChidClassA()中的super改为:super(ChidClassC, self).__init__(),程序就会无限递归下去。

    Enter ChildClassA
    Enter ChildClassA
    Enter ChildClassA
    ...
    Enter ChildClassA
    Enter ChildClassA
    Enter ChildClassA
    Enter ChildClassA
      File "D:/Python20190819/WebApp/venv/Include/testunit.py", line 53, in <module>
        c = ChildClassC()
      File "D:/Python20190819/WebApp/venv/Include/testunit.py", line 41, in __init__
        super(ChildClassC, self).__init__()
      File "D:/Python20190819/WebApp/venv/Include/testunit.py", line 41, in __init__
        super(ChildClassC, self).__init__()
      File "D:/Python20190819/WebApp/venv/Include/testunit.py", line 41, in __init__
        super(ChildClassC, self).__init__()
      [Previous line repeated 992 more times]
      File "D:/Python20190819/WebApp/venv/Include/testunit.py", line 40, in __init__
        print('Enter ChildClassA')
    RecursionError: maximum recursion depth exceeded while calling a Python object

    3、super()避免重复调用

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

    """
    单继承 super().__int__()和 Base.__init__(self)是一样的, super()避免了基类的显式调用。
    
    class Base(object):
        def __init__(self):
            print('Create Base')
    
    class ChildClassA(Base):
        def __init__(self):
            print('Create ChildClassA')
            super().__init__()
    
    class ChildClassB(Base):
        def __init__(self):
            print('Create ChildClassB')
            super().__init__()
    
    
    ChildClassA()
    #输出
    #Create ChildClassA
    #Create Base
    """
    
    """
    多继承:
    注意:多继承时,会设计继承顺序,supper()相当于返回继承顺序的下一个类,而不是父类。
    """
    
    class Base(object):
        def __init__(self):
            print('Create Base')
    
    class ChildClassA(Base):
        def __init__(self):
            print('Enter ChildClassA')
            Base.__init__(self)
            print('Leave ChildClassA')
    
    class ChildClassB(ChildClassA,Base):
        def __init__(self):
            print('Enter ChildClassB')
            ChildClassA.__init__(self)
            Base.__init__(self)
            print('Leave ChildClassB')
    
    b = ChildClassB()
    
    # 输出:
    Enter ChildClassB
    Enter ChildClassA
    Create Base
    Leave ChildClassA
    Create Base
    Leave ChildClassB

    supper() 避免重复

    """
    单继承 super().__int__()和 Base.__init__(self)是一样的, super()避免了基类的显式调用。
    
    class Base(object):
        def __init__(self):
            print('Create Base')
    
    class ChildClassA(Base):
        def __init__(self):
            print('Create ChildClassA')
            super().__init__()
    
    class ChildClassB(Base):
        def __init__(self):
            print('Create ChildClassB')
            super().__init__()
    
    
    ChildClassA()
    #输出
    #Create ChildClassA
    #Create Base
    """
    
    """
    多继承:
    注意:多继承时,会设计继承顺序,supper()相当于返回继承顺序的下一个类,而不是父类。
    """
    
    class Base(object):
        def __init__(self):
            print('Create Base')
    
    class ChildClassA(Base):
        def __init__(self):
            print('Enter ChildClassA')
            super( ).__init__()
            print('Leave ChildClassA')
    
    class ChildClassB(ChildClassA,Base):
        def __init__(self):
            print('Enter ChildClassB')
            super().__init__()
            print('Leave ChildClassB')
    
    b = ChildClassB()
    
    # 输出:
    Enter ChildClassB
    Enter ChildClassA
    Create Base
    Leave ChildClassA
    Leave ChildClassB

     参考自:开源中国 http://my.oschina.net/jhao104/blog/682322

  • 相关阅读:
    0102-进程操作(面向对象简单工厂模式,打开输入文件)
    0101-进程操作(变量命名)
    win10无法成功完成操作因为文件包含病毒或潜在的垃圾软件如何处理
    序列化和反序列化
    __slot__的用法
    python中typeguard包
    pandas如何将多个DataFrame写入同一个excel工作簿中
    DEAP库遗传算法
    【教程】如何把喜马拉雅音频下载到电脑
    oracle安装路径查看方式
  • 原文地址:https://www.cnblogs.com/AndyChen2015/p/11428212.html
Copyright © 2011-2022 走看看