深入理解python super

Python中的方法解析顺序深入理解即super()和Method Resolution Order详解 Python和其它任何面向对象的语言都需要面对多继承的问题,多继承会带来非常复杂的问题,包括类的多继承和函数的多继承等。而全网中目前很少有人能参考python的官方文档对super函数和Method Resolution Order进行较为准确的分析。在这里,我对这两个问题进行分析和记录,如有问题,欢迎讨论。 阅读详情

在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如:

class Animal(object):
    def __init__(self, name):
        self.name = name
    def greet(self):
        print 'Hello, I am %s.' % self.name

class Dog(Animal):
    def greet(self):
        super(Dog, self).greet()   # Python3 可使用 super().greet()
        print 'WangWang...'

在上面,Animal 是父类,Dog 是子类,我们在 Dog 类重定义了 greet 方法,为了能同时实现父类的功能,我们又调用了父类的方法,看下面的使用:

>>> dog = Dog('dog')
>>> dog.greet()
Hello, I am dog.
WangWang..

super 的一个最常见用法可以说是在子类中调用父类的初始化方法了,比如:

class Base(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

class A(Base):
    def __init__(self, a, b, c):
        super(A, self).__init__(a, b)  # Python3 可使用 super().__init__(a, b)
        self.c = c

深入 super()

看了上面的使用,你可能会觉得 super 的使用很简单,无非就是获取了父类,并调用父类的方法。其实,在上面的情况下,super 获得的类刚好是父类,但在其他情况就不一定了,super 其实和父类没有实质性的关联。

让我们看一个稍微复杂的例子,涉及到多重继承,代码如下:

class Base(object):
    def __init__(self):
        print "enter Base"
        print "leave Base"

class A(Base):
    def __init__(self):
        print "enter A"
        super(A, self).__init__()
        print "leave A"

class B(Base):
    def __init__(self):
        print "enter B"
        super(B, self).__init__()
        print "leave B"

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

其中,Base 是父类,A, B 继承自 Base, C 继承自 A, B,它们的继承关系是一个典型的『菱形继承』,如下:

      Base
      /  \
     /    \
    A      B
     \    /
      \  /
       C

现在,让我们看一下使用:

>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C

如果你认为 super 代表『调用父类的方法』,那你很可能会疑惑为什么 enter A 的下一句不是 enter Base 而是 enter B。原因是,super 和父类没有实质性的关联,现在让我们搞清 super 是怎么运作的。

MRO 列表

事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序,我们可以使用下面的方式获得某个类的 MRO 列表:

>>> C.mro()   # or C.__mro__ or C().__class__.mro()
[__main__.C, __main__.A, __main__.B, __main__.Base, object]

那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:

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

super 原理

super 的工作原理如下:

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

其中,cls 代表类,inst 代表实例,上面的代码做了两件事:

  • 获取 inst 的 MRO 列表
  • 查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1]

当你使用 super(cls, inst) 时,Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类。

现在,让我们回到前面的例子。

首先看类 C 的 __init__ 方法:

super(C, self).__init__()

这里的 self 是当前 C 的实例,self.class.mro() 结果是:

[__main__.C, __main__.A, __main__.B, __main__.Base, object]

可以看到,C 的下一个类是 A,于是,跳到了 A 的 __init__,这时会打印出 enter A,并执行下面一行代码:

super(A, self).__init__()

注意,这里的 self 也是当前 C 的实例,MRO 列表跟上面是一样的,搜索 A 在 MRO 中的下一个类,发现是 B,于是,跳到了 B 的 __init__,这时会打印出 enter B,而不是 enter Base。

整个过程还是比较清晰的,关键是要理解 super 的工作方式,而不是想当然地认为 super 调用了父类的方法。

小结

  • 事实上,super 和父类没有实质性的关联。

  • super(cls, inst) 获得的是 cls 在 inst 的 MRO 列表中的下一个类。

转自:https://funhacks.net/explore-python/Class/super.html

深入理解Python多重继承与super()方法 本文深入探讨了Python中的多重继承机制和super()方法的使用。多重继承允许一个类继承多个父类的特性,但随之而来的是方法解析顺序(MRO)的复杂性。文章通过示例解释了如何计算MRO,并通过例子展示了super()方法在单继承和多重继承中的应用,以及如何在多层继承中调用特定父类的构造函数或方法。 阅读详情

相关推荐

深入理解Python多重继承与super()的正确使用

本文详细探讨了Python中多重继承的MRO算法及其重要性,并通过实例展示了如何正确使用super()方法。文章首先解释了类的线性化过程,然后通过具体的例子演示了如何计算MRO并应用到实际代码中。此外,还探讨了在继承中构造函数的行为以及super()方法的使用,包括调用特定父类的方法和访问父类静态变量。

weixin_36289813的博客 473

python中子类调用父类的方法

python super() 一、问题的发现与提出   在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1:  代码段1: class A: def __init__(self): print "enter A" print "leave A" class B(A): def __init__(sel...

Arlingtonroad的博客 6322

自适应滤波算法综述

自适应滤波算法综述

xdzhujy的博客 5万+

Python关于super的用法总结【super是否带参数的区别】

super().aa(a, b) 和 super(Test001, self).aa(a, b) 默认是等级的【但是在有些特殊情况,则必须指定super的参数】 class Test: def aa(self, a, b): while True: print(a, b) class Test001(Test): def aa(self, a, b): """ 功能:重写父类方法 ...

weixin_43343144的博客 1976

csp-j/s

CSP-J/S 是中国计算机学会(CCF)主办的 ‌‌(Certified Software Professional Junior/Senior),是信息学奥赛(NOI)体系的入门级选拔考试,也是国内最具权威性的青少年编程能力认证之一。

gxyxxrYYDS的博客 2029

QMT Python API 实战指南:从安装到策略开发的完整流程

本文提供了一份详尽的QMT Python API实战指南,涵盖从环境配置到策略开发的完整流程。文章深入解析了xtdata行情模块与xttrader交易模块的核心架构与协作方式,并通过一个双均线策略实例,手把手教你如何获取数据、计算信号并执行交易,是量化交易开发者快速上手QMT Python接口文档的实用教程。

butter的博客 1416

super()的两个参数

python中super(a,b)的两个参数,表示获取b的mro表中a的下一个类 并且super(x,self)在执行中self始终指向调用类,见如下代码 输出结果如下 可见self始终指向D的对象 参考:https://blog.youkuaiyun.com/zhangjg_blog/article/details/83033210(感谢这位博客作者) ...

健忘者 2878

Keil MDK安装NRF52832开发环境全攻略(附系统时间错误解决方案)

本文详细介绍了如何使用Keil MDK搭建NRF52832开发环境,包括基础软件安装、项目配置关键步骤以及常见问题解决方案。特别针对系统时间错误导致的编译失败问题提供了实用解决方法,帮助开发者快速上手NRF52832开发。

weixin_29168153的博客 506

super() 的入门使用

本文出处:http://python.jobbole.com/86787/super() 的入门使用在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用super来实现,比如:12345678910class Animal(object):def __init__(self...

weixin_33825683的博客 472

【CAN总线测试】——通讯相关诊断测试

本章主要介绍通讯相关诊断测试用例设计

LOVE135149的博客 1815

ADRC自抗扰算法优化(PLC梯形图篇)

ADRC自抗扰算法PLC梯形图完整源代码请参看下面博客文章:ADRC自抗扰控制算法(含梯形图完整源代码和算法公式)_adrc算法_RXXW_Dor的博客-优快云博客PLC的自抗扰控制(ADRC)算法_RXXW_Dor的博客-优快云博客_adrc算法1、自抗扰控制算法,网上很多文章有所讲解,大家也可以关注韩京清教授的论文和书籍,这里就不赘述了,下面给出梯形图+SCL代码。

RXXW_Dor的博客 2283

python中super用法

Python中的super用法介绍

chase 1万+

GIS常用符号化色带(超级色带)根据python制作

GIS自带的色带比较单一,今天分享一款色带,应用之后大家出图的时候可以选择更多的配色,符号化/点击色块/样式引用/将样式添加至列表即可。色带类型比较多,大家可以自己尝试下不同的风格。简单符号化一下,看看效果。以中国县级行政区划为例,

J_Giser的博客 2639

python的super方法_深入理解Python中的super()方法

前言python的类分别有新式类和经典类,都支持多继承。在类的继承中,如果你想要重写父类的方法而不是覆盖的父类方法,这个时候我们可以使用super()方法来实现python语言与C++有相似的类继承,在类定义时,python中会自定义第一个self,类似C++中this指针,指向对象自身。python简单的类举例:>>> class hello(object):... def print_...

weixin_39856630的博客 95

Python内置函数zip()——《Python内置函数手册》Python老吕编著

zip()函数是 Python 中的一个内置函数,用于将多个可迭代对象(如列表、元组、字符串等)中对应的元素打包成一个个元组,然后返回由这些元组组成的迭代器。zip()函数常用于将多个序列并行迭代,或者用于数据对齐。zip()它返回一个迭代器,这意味着你可以逐个获取打包后的元素,而不是一次性将所有元素加载到内存中。如果输入的可迭代对象长度不一致,zip()会以最短的可迭代对象为准,只打包到最短对象的末尾。它可以用来并行迭代多个序列,使得代码更加简洁和高效。在接下来的章节中,我们将详细介绍。

Python老吕的博客 682

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

python深入理解super

python 深入理解super(),多级继承的时候,控制继承的属性

DaxiaLeeSuper的博客 408

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

python中super方法的作用_深入理解Python中的super()方法

前言python的类分别有新式类和经典类,都支持多继承。在类的继承中,如果你想要重写父类的方法而不是覆盖的父类方法,这个时候我们可以使用super()方法来实现python语言与C++有相似的类继承,在类定义时,python中会自定义第一个self,类似C++中this指针,指向对象自身。python简单的类举例:>>> class hello(object):... def print_...

weixin_39593469的博客 844

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Python3深入理解super()函数

目录前言描述语法单继承方式多继承方式总结 前言 深入理解super()函数在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用super()函数来实现。 描述 super() 函数是用于调用父类(超类)的一个方法。 super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,...

无梦生7的博客 646

深入理解Python中的super()函数 - 探索Python项目解析

在日常Python开发中,`super()`函数看似简单,但很多开发者对其工作原理存在误解。你是否曾遇到过这样的困惑:在多重继承场景中,`super()`调用的顺序与预期不符?或者在使用`super()`时遇到了难以调试的问题? 本文将带你深入探索`super()`函数的内部机制,通过实际代码示例、流程图和对比表格,彻底理解这个看似简单却暗藏玄机的Python特性。 ## 一、super()函

gitblog_00605的博客 613

深入理解Python中的super()函数:它真的调用了父类吗?

Python中的super()函数常被误解为直接调用父类方法,实际上它是按照方法解析顺序(MRO)调用下一个类的方法。文章通过代码示例和MRO图解,揭示了super()在多重继承中的真实行为,展示了协作式方法调用的特点,并分析了常见误区和最佳实践。关键点包括:super()依赖MRO而非简单父类调用、多重继承中的方法调用顺序、以及如何正确使用super()实现灵活继承结构。理解这些概念有助于开发更健壮的面向对象Python代码。

软件科学-郝学胜 920

深入理解Python虚拟机:super超级魔法的背后原理

在 Python 当中 super 的使用方式分为两种一种是可以直接使用参数,另外一种是在类的方法当中不使用参数,后者的实现稍微复杂一点,他会从当前栈帧和局部变量表当中分别取出类对象和类,作为 super 的参数,从而实现 super 的功能。当对象进行方法调用的时候,就会从类的 mro 当中的第一个类开始寻找,直到最后一个类为止,当第一次发现对应的类有相应的方法时就进行返回就调用这个类的这个方法。为什么要进行这样的处理呢,这是因为需要调用相应位置类的父类方法,因此所有的使用 super 的位置的。

qq_45537774的博客 307

pythonsuper继承规则,深入理解Python中的super()方法

前言python的类分别有新式类和经典类,都支持多继承。在类的继承中,如果你想要重写父类的方法而不是覆盖的父类方法,这个时候我们可以使用super()方法来实现python语言与C++有相似的类继承,在类定义时,python中会自定义第一个self,类似C++中this指针,指向对象自身。python简单的类举例:>>> class hello(object):... d...

weixin_34938347的博客 153

深入理解python面向对象_Python -- 面向对象的三大特性及深入了解super()

面向对象的三大特性:继承(在上节),封装,多态封装:将一些东西内容封装到一个地方,还可以取出来(例如:类设置静态属性,设置一些方法)​调用被封装的内容,有两种情况: 1. 通过对象直接调用 2. 通过self间接调用多态:一个事物的多种形态,Python中默认支持多态.鸭子类型(面试会问): A,B两个类,没有任何关系(完全没有耦合性),独立的两个,但里面的功能相似,所以Python一般会将类...

weixin_39615499的博客 114

python的super() 转载runoob

https://www.runoob.com/w3cnote/python-super-detail-intro.html

weixin_44728985的博客 184
上一篇: keepalived配置手册(V1.2.24)中文版详解
下一篇: 浅谈 Python 的 with 语句
考拉先生
博客等级 码龄15年 5粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值