zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

Python 函数 基于 初始化 Super
2023-09-11 14:14:24 时间

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

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

class Base:
    def __init__(self):
        print("Base = __init__")


class A(Base):
    def __init__(self):
        Base.__init__(self)
        print("A = __init__")

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

class Base:
    def __init__(self):
        print("Base = __init__")


class A(Base):
    def __init__(self):
        Base.__init__(self)
        print("A = __init__")


class B(Base):
    def __init__(self):
        Base.__init__(self)
        print("B = __init__")


class C(A, B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)
        print("C = __init__")


if __name__ == '__main__':
    c = C()
    print(c)

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

Base = __init__
A = __init__
Base = __init__
B = __init__
C = __init__
<__main__.C object at 0x000001D51899BE50>

Process finished with exit code 0

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

class Base:
    def __init__(self):
        print("Base = __init__")


class A(Base):
    def __init__(self):
        super().__init__()
        print("A = __init__")


class B(Base):
    def __init__(self):
        super().__init__()
        print("B = __init__")


class C(A, B):
    def __init__(self):
        super().__init__()
        print("C = __init__")


if __name__ == '__main__':
    c = C()
    print(c)

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

Base = __init__
B = __init__
A = __init__
C = __init__
<__main__.C object at 0x000001B462C9A6B0>

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

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

if __name__ == '__main__':
    print(C.mro())


# 运行结果
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

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()的重新定义后的方法覆盖(也就是重写),自然就不会出现多次调用的效果了。

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

未完成,待续……

我推荐一个【Python自动化测试交流群:746506216】,大家可以一起探讨交流软件测试,共同学习软件测试技术、面试等软件测试方方面面,助你快速进阶Python自动化测试/测试开发,走向高薪之路。

喜欢软件测试的小伙伴们,如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一 键三连哦!