编程学习网 > 编程语言 > Python > Python教程:Python中的super()如何使用
2024
03-08

Python教程:Python中的super()如何使用


我们在使用 Python 进行面向对象编程时可能会遇到一个函数super(),那么它是什么?在类继承中它又起到了什么作用呢?今天这篇文章将带你走近Python的super()函数。


什么是super()函数?
Python 中的super()函数允许子类将任务委托给它的父类或祖先树中的某个类。使用语法是super().method_name(args)。

下面通过两段代码来展示单继承中如何使用super()。

案例1

class ClassOne:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
    def add_vars(self):
        return self.var1 + self.var2

class ClassTwo(ClassOne):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
在这里,ClassTwo 继承自 ClassOne。现在让我们创建一个ClassTwo的对象。

由于它继承自ClassOne,如果我们调用ctwo.add_vars(),会发生什么?

two = ClassTwo(3,4)

# 会发什么什么呢?
two.add_vars()
如果你认为结果会导致错误,那么你是正确的。它会返回AttributeError: 'ClassTwo' object has no attribute 'var1'。这里没有设置var1和var2的值,因为你从未初始化 ClassOne。

案例2

class ClassOne:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
    def add_vars(self):
        return self.var1 + self.var2

class ClassTwo(ClassOne):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
        # 我们增加了这行代码
        super().__init__(v1, v2) 
在这个案例中,如果你创建一个名为ctwo = ClassTwo(3,4)的ClassTwo对象,然后调用ctwo.add_vars(),它将返回7。这就是super()函数的简单用法。它会委托给实例祖先树中的函数。

two = ClassTwo(3,4)

two.add_vars()
结果:

7
注意!!!

如果你将super().__init__(v1,v2)修改为ClassOne.__init__(self,v1,v2),它也会起到同样的作用。

但是调用super()更好,因为你不需要指定委托类的名称。它是一个计算得出的间接引用。如果明天有人更改了被委托类的名称,你的代码仍然可以正常工作。

多重继承
在多重继承的情况下,处理super()会有点麻烦,而方法解析顺序__mro__的作用就显现出来了。

考虑下面的例子,我们有一个类 Three 继承自两个类 One 和 Two。

class One:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
        
    def add_var(self):
        return self.var1 + self.var2

class Two:
    def __init__(self, var3, var4):
        self.var3 = var3
        self.var4 = var4
        
    def add_var_2(self):
        return self.var3 + self.var4

class Three(One,Two):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
        super().__init__(v1, v2)
现在假设我们创建一个名为three = Three(3,4)的 Three 类的对象。如果我们调用three.add_var()和three.add_var_2()会发生什么?第一个调用会返回7,而第二个调用会返回AttributeError: 'Three' object has no attribute 'var3'。

这是因为 Three 的__mro__是[Three, One, Two],你可以使用print(Three.__mro__)命令打印出来。通常,MRO 是使用 C3 算法计算的。

那么我们如何让three.add_var_2()成功调用呢?

我最初考虑的是调用两次super(),但实际上并不起作用。它只会按照 MRO 的顺序到达 Class One ,然后停止。

为此我想到了上一章的问题,我们可以显式的初始化每一个父类,如下所示。

class One:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
        
    def add_var(self):
        return self.var1 + self.var2

class Two:
    def __init__(self, var3, var4):
        self.var3 = var3
        self.var4 = var4
        
    def add_var_(self):
        return self.var3 + self.var4

class Three(One,Two):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
        One.__init__(self, v1, v2)
        Two.__init__(self, v1, v2)
现在,如果你使用three = Three(3,4)创建一个对象,然后调用three.add_var()或three.add_var_2(),它每次都会返回7,而且没有错误。

当我对我发现的解决方案感到高兴时,我在 stackoverflow 上找到了一个帖子。它说父类也应该调用super(),以确保与子类协同工作。

在父类中使用super()的代码如下所示:

class One:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
        # 增加的代码
        super().__init__(var1, var2)
        
    def add_var(self):
        return self.var1 + self.var2

class Two:
    def __init__(self, var3, var4):
        self.var3 = var3
        self.var4 = var4
        # 增加的代码
        super().__init__()
        
    def add_var_(self):
        return self.var3 + self.var4

class Three(One,Two):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
        # 修改的部分
        super().__init__(v1,v2)

在类 One 中,我们必须通过super().__init__传递变量,而在类 Two 中则不必。这是因为 MRO(方法解析顺序)是[Three, One, Two],所以 One 的__init__调用了 Two 的__init__,而 Two 的__init__调用了所有类的根类,它不需要任何变量。此外,如果你传递了变量,会导致错误。

这意味着,如果你想以协同类的方式调用super()函数,我们必须了解它在子类中的使用方式(至少在上面的例子中是如此)。

写在最后

总之,作为开发人员,必须了解这两种使用方式。根据实际需求选用ParentClass.function_name(self,*(args))或者使用super().function_name(*(args))来调用父函数,并根据其优点选择其中之一。

以上就是Python教程:Python中的super()如何使用的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取