python super()函数的详解

 更新时间:2021年11月25日 09:41:38   作者:程序员-夏天  
这篇文章主要为大家介绍了python super()函数,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

Python是一门面向对象的语言,定义类时经常要用到继承,在类的继承中,子类继承父类中已经封装好的方法,不需要再次编写,如果子类如果重新定义了父类的某一方法,那么该方法就会覆盖父类的同名方法,但是有时我们希望子类保持父类方法的基础上进行扩展,而不是直接覆盖,就需要先调用父类的方法,然后再进行功能的扩展,这时就可以通过super来实现对父类方法的调用。

super的用法

看下面一个例子:

class A:
    def func(self):
        print("A的func执行")
class B(A):
    def func(self):
        super().func()
        print("B扩展的func执行")
b = B()
b.func()

# 输出结果为:
# A的func执行
# B扩展的func执行

上面程序中,A是父类,B是A的子类,我们在A类中重定义了func()方法,在B类中重新定义了func()方法,在方法中通过super().func()又调用了父类的方法,所以执行结果才会有A类func()方法输出。

如果经常看Python内置库及第三方库源码的话,你会发现,super用的非常多的地方是在子类中调用父类的初始化__init__()方法,这种用法非常常见。

class A:
    def __init__(self, x):
        self.x = x
class B(A):
    def __init__(self, x, y):
        super().__init__(x)
        self.y = y
b = B(1, 2)
print(b.x, b.y)

看到这,你会想到super就是用来获取父类并用来调用父类方法的,这样说对不对呢,其实是不对的,使用supper获取的不是父类,而是MRO列表中的下一个类,所谓MRO列表即方法解析顺序(Method Resolution Order)列表,它代表着类继承的顺序,我们可以使用以下几种获得某个类的MRO列表:

C.mro()
C.__mro__
c.__class__.__mro__

MRO列表的顺序确定经历了很多次的变迁,最新的是通过C3线性化算法来实现的,感兴趣的话可以自行了解一下,总的来说,一个类的MRO列表就是合并所有父类的MRO列表,并遵循以下三条原则:

  • 子类永远在父类前面
  • 如果有多个父类,会根据它们在列表中的顺序被检查
  • 如果对下一个类存在两个合法的选择,选择第一个父类

下面来看一下下面这个例子:

class A(Base):
    def func(self):
        print("A的func执行")
        super().func()
        print("A的func执行完毕")
class B(Base):
    def func(self):
        print("B的func执行")
        super().func()
        print("B的func执行完毕")
class C(A, B):
    def func(self):
        print("C的func执行")
        super().func()
        print("C的func执行完毕")
c = C()
c.func()
# 获取MRO列表
print(c.__class__.__mro__)

执行结果如下:

上述程序中,Base是父类,A、B都继承自Base,C继承自 A、B,它们的继承关系就是一个典型的菱形继承,如下:

通过结果我们可以看出,super并不是获取父类并用来调用父类的方法,而是根据MRO列表一次调用下一个类,使用c.__class__.__mro__可以获取MRO列表,MRO列表的顺序是C、A、B、Base、object。

super的原理

super计算方法解析顺序中的下一个类,可以接收两个参数:

def super(cls, inst):
    mro = inst.__class__.mro()
    return mro[mro.index(cls) + 1]

总结

现在我们知道:supper获取的是MRO列表中的下一个类,当前类的父类没有实质性的关系;还有如何查看MRO列表。最后需要注意的是super以及MRO列表,针对都是Python新式类!

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • Python接口传输url与flask数据详解

    Python接口传输url与flask数据详解

    这篇文章主要介绍了Python通过接口传输url与flask数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-09-09
  • Python图像运算之图像灰度非线性变换详解

    Python图像运算之图像灰度非线性变换详解

    这篇文章将详细讲解图像灰度非线性变换。图像灰度非线性变换主要包括对数变换、幂次变换、指数变换、分段函数变换,通过非线性关系对图像进行灰度处理,本文主要讲解三种常见类型的灰度非线性变换,感兴趣的可以了解一下
    2022-03-03
  • Python实现在Excel文件中写入图表

    Python实现在Excel文件中写入图表

    这篇文章主要为大家介绍了如何利用Python语言实现在Excel文件中写入一个比较简单的图表,文中的实现方法讲解详细,快动手尝试一下吧
    2022-05-05
  • Python中格式化字符串输出的4种方式小结

    Python中格式化字符串输出的4种方式小结

    本文主要介绍了Python中格式化字符串输出的4种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • django项目环境搭建及在虚拟机本地创建django项目的教程

    django项目环境搭建及在虚拟机本地创建django项目的教程

    这篇文章主要介绍了django项目环境搭建及在虚拟机本地创建django项目的教程,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • python模块导入方式浅析步骤

    python模块导入方式浅析步骤

    这篇文章主要为大家介绍了python中模块导入的方式,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • linux中使用Python对图片进行批量命名

    linux中使用Python对图片进行批量命名

    大家好,本篇文章主要讲的是linux中使用Python对图片进行批量命名,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Python生成短uuid的方法实例详解

    Python生成短uuid的方法实例详解

    python的uuid都是32位的,比较长,处理起来效率比较低。这篇文章主要介绍了Python生成短uuid的方法,需要的朋友可以参考下
    2018-05-05
  • python实现远程运行bat文件

    python实现远程运行bat文件

    这篇文章主要介绍了python实现远程运行bat文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • python实现双链表

    python实现双链表

    这篇文章主要为大家详细介绍了python实现双链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论