• python:基于super()函数初始化


    super() 函数的一种常见用途就是继承父类时,调用父类方法,能确保父类被正常初始化。


    通常在继承类中我们可以看到直接调用父类中的方法,就像下面这样:

    1. class Base:
    2.     def __init__(self):
    3.         print("Base = __init__")
    4. class A(Base):
    5.     def __init__(self):
    6.         Base.__init__(self)
    7.         print("A = __init__")

    尽管在继承类中可以这样直接调用父类使用,但是在多继承中就会出现多次调用的情况。比如下面这个例子:

    1. class Base:
    2.     def __init__(self):
    3.         print("Base = __init__")
    4. class A(Base):
    5.     def __init__(self):
    6.         Base.__init__(self)
    7.         print("A = __init__")
    8. class B(Base):
    9.     def __init__(self):
    10.         Base.__init__(self)
    11.         print("B = __init__")
    12. class C(A, B):
    13.     def __init__(self):
    14.         A.__init__(self)
    15.         B.__init__(self)
    16.         print("C = __init__")
    17. if __name__ == '__main__':
    18.     c = C()
    19.     print(c)

    上面的代码运行后,会发现 “ Base = __init__ ” 被调用了两次。就像下面这样:

    1. Base = __init__
    2. A = __init__
    3. Base = __init__
    4. B = __init__
    5. C = __init__
    6. <__main__.C object at 0x000001D51899BE50>
    7. Process finished with exit code 0

    当然这样调用并不是不可以,也没有什么害处。但也不排除出现问题的可能性,所以尽量规范去调用,将代码修改为使用super()后,那么一切工作就能正常工作了(官方推荐使用 “ super().__int__() ” 调用):

    1. class Base:
    2.     def __init__(self):
    3.         print("Base = __init__")
    4. class A(Base):
    5.     def __init__(self):
    6.         super().__init__()
    7.         print("A = __init__")
    8. class B(Base):
    9.     def __init__(self):
    10.         super().__init__()
    11.         print("B = __init__")
    12. class C(A, B):
    13.     def __init__(self):
    14.         super().__init__()
    15.         print("C = __init__")
    16. if __name__ == '__main__':
    17.     c = C()
    18.     print(c)

    代码修改为super()调用并运行后,就会发现每个__init__()只调用了一次(这种调用是规范的,也是官方推荐的)。就像下面这样:

    1. Base = __init__
    2. B = __init__
    3. A = __init__
    4. C = __init__
    5. <__main__.C object at 0x000001B462C9A6B0>

    为什么两种调用产生的结果会不一致呢?

    首先python的继承时,会计算出一个解析顺序的MRO的只读列表。就像下面这样:

    1. if __name__ == '__main__':
    2.     print(C.mro())
    3. # 运行结果
    4. [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
    5. Process finished with exit code 0

    MRO列表中,可看到继承的顺序是先自己本身,继承了两个类的时候是先左后右,如果父类还有继承则再继续找父类的父类,最后再找到原始基类(object),这也是继承运行的执行顺序。

    “ Base = __init__ ” 被调用了两次的原因是因为A类中继承Base父类,B类中也继承了Base父类,然后C又继承了A、B父类,这个时候运行C类时,C在初始化时分别调用了“ A.__init__(self) ”“ B.__init__(self) ”,最后结果就必然会产生Base基类被多次调用的效果了。

    当修改为“ super().__init__() ” 时,没有产生多次调用的原因则是每个类在初始化时都进行了super()的重新定义后的方法覆盖(也就是重写),自然就不会出现多次调用的效果了。


    今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!

    未完成,待续……

    一直在努力,希望你也是!

    微信搜索公众号:就用python

  • 相关阅读:
    基于matlab创建基于物理统计的雷达模型(附源码)
    Apollo安装全攻略
    由浅入深理解C#中的事件
    程序员脱单秘籍 | 我跟JVM搞对象!【深度剖析对象的创建和内存分配】
    Golang骚操作——使用runtime私有函数
    数值分析思考题(钟尓杰版)参考解答——第四章
    前后端分离springBoot项目集成部署vue
    计算机毕业设计(附源码)python政府项目管理平台
    【c++刷题Day3】专题3T2
    交通物流模型 | 基于时空注意力融合网络的城市轨道交通假期短时客流预测
  • 原文地址:https://blog.csdn.net/LIFENG0402/article/details/125607692