python super()函数的详解

作者:程序员-夏天 时间:2023-08-08 10:09:42 

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__)

执行结果如下:

python super()函数的详解

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

python super()函数的详解

通过结果我们可以看出,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]

来源:https://blog.csdn.net/weixin_50097774/article/details/121521738

标签:python,super(),函数
0
投稿

猜你喜欢

  • 如何使用Python优雅的合并两个字典Dict

    2023-10-12 22:50:36
  • 详解python 字符串和日期之间转换 StringAndDate

    2021-11-17 03:40:56
  • python如何通过实例方法名字调用方法

    2021-04-24 09:00:31
  • JavaScript的eval JSON object问题

    2024-05-09 10:33:59
  • Python爬虫爬取美剧网站的实现代码

    2021-07-11 01:05:04
  • pandas 如何保存数据到excel,csv

    2021-05-12 13:05:22
  • python 获取当前目录下的文件目录和文件名实例代码详解

    2022-07-21 21:31:25
  • Sublime Text3快捷键汇总

    2023-08-22 18:41:57
  • vue elementUI实现自定义正则规则验证

    2024-05-28 16:00:58
  • Golang 统计字符串字数的方法示例

    2024-02-17 07:35:44
  • python进阶教程之模块(module)介绍

    2021-06-16 12:52:07
  • 利用OpenCV和Python实现查找图片差异

    2023-01-06 07:22:22
  • python代码实现小程序登录流程时序总结

    2022-10-16 17:30:14
  • MYSQL日志的正确删除方法详解

    2024-01-22 13:18:02
  • mysql 存在该记录则更新,不存在则插入记录的sql

    2024-01-29 07:19:24
  • Python:通配符查找、拷贝文件的操作

    2021-09-05 13:05:03
  • pytest使用@pytest.mark.parametrize()实现参数化的示例代码

    2022-07-17 07:54:01
  • Python解析命令行读取参数之argparse模块

    2021-12-17 22:15:32
  • Python实现对一个函数应用多个装饰器的方法示例

    2022-01-23 17:30:22
  • 理解 XMLDOM 的节选

    2008-02-17 14:48:00
  • asp之家 网络编程 m.aspxhome.com