您的位置:

Python工程师必知:super()__init__()用法

在Python面向对象编程中,我们经常需要调用父类的构造函数,而调用父类构造函数的一种常用方法是使用super()函数,其搭配的关键字是__init__()函数。

一、super()函数的概念

super()函数用于调用父类中的方法,可以避免在子类实现中重复写出父类的方法名,实现了代码复用与维护的便利。

当父类中出现同名函数的时候,使用super()可以保证调用了正确的函数。这是因为super()会按照方法解析顺序(MRO)的顺序来查找父类中的方法,而不是在当前类中查找。

MRO是一种线性化的方法解析顺序,它定义了子类中的方法搜索顺序,每个类都有一个MRO列表,按照从左至右,深度优先的顺序排列。

class A:
    def __init__(self):
        print('调用A类构造函数')
        
class B(A):
    def __init__(self):
        super().__init__()
        print('调用B类构造函数')
        
b = B()

运行结果:

调用A类构造函数
调用B类构造函数

上例中,子类B继承自父类A,并在构造函数中调用了父类A的构造函数。在调用super().__init__()时,会调用父类A的构造函数,输出“调用A类构造函数”的信息,然后再执行自身的构造函数,输出“调用B类构造函数”的信息。

二、super()函数使用时应注意的问题

1. super()函数的参数

super()函数有两种常见的调用形式,一种是super(当前类名, self);另一种是super(父类名, 子类实例)。

第一种调用形式中,当前类名可以省略,直接传入self,Python解释器会自动根据当前类确定要调用的父类。

class A:
    def foo(self):
        print('调用A类方法')

class B(A):
    def foo(self):
        super().foo()

b = B()
b.foo()

运行结果:

调用A类方法

上例中,子类B继承自父类A,重写了foo方法,并在foo方法中使用super().foo()调用了父类A的foo方法。

第二种调用形式中,可以手动指定要调用的父类名称,Python解释器会根据该名称按照类的继承关系来确定要调用的父类。

class A:
    def foo(self):
        print('调用A类方法')

class B(A):
    def foo(self):
        super(A, self).foo()

b = B()
b.foo()

运行结果:

调用A类方法

上例中,子类B继承自父类A,重写了foo方法,并在foo方法中使用super(A, self).foo()调用了父类A的foo方法。

2. super()函数与多继承的关系

在多继承的情况下,使用super()函数调用的是MRO列表中的下一个类的方法,而不是当前类的父类的方法。

class A:
    def foo(self):
        print('调用A类方法')

class B:
    def foo(self):
        print('调用B类方法')

class C(A, B):
    def foo(self):
        super().foo()

c = C()
c.foo()

运行结果:

调用B类方法

上例中,子类C继承自父类A和B,并在foo方法中使用super().foo()调用了父类A和B的foo方法。在Python中,多继承使用DFS算法创建MRO列表。因此MRO列表中的顺序为[C, A, B, object],super()函数调用的是MRO列表中的下一个类的方法,即B类的foo方法。

三、总结

super()函数是Python中非常重要的一个函数,用于调用父类的方法。在使用时应注意其参数的传入方式,以及在多继承的情况下的使用。

合理使用super()函数可以提高代码的可读性、减少代码重复和维护成本,是每个Python工程师都需要掌握的基本技能。