引言:最近在用Pytorch搭建深度学习模型,创建类Net()的时候,需要继承父类nn.Module,在__init__()函数中添加super(Net, self).__init__(),于是对super产生了疑惑,进行了一番学习后,豁然开朗,写下这篇文章供自己日后查阅使用。

super

super()可以用于调用父类(超类)的某个方法,并且只能用于新式类(后面内容会讲经典类与新式类),主要用在多继承中,在单继承时直接调用父类方法即可,但是在多继承中就会涉及到重复继承等问题,这里也需要牵涉到MRO(Method Resolution Order,方法解析顺序)。super()形式如下:super(type[, object-or-type]),type -- 类,object-or-type -- 类,一般是 self,如下所示。

class Net(nn.Module):

def __init__(self):

super(Net, self).__init__()

在这个例子中,Net类继承nn.Module,并且调用nn.Module的初始化方法,但是这是一个简单的单继承关系,但是更复杂的情况下,比如多继承时,该如何调用方法呢?(调用方法,需要对当前类和基类进行搜索以确定方法所在的位置)下图为钻石继承,类D继承类B和类C,类B和类C都继承A,类C和类A都有方法method,那么D.method()到底调用的是A.method()还是C .method()?如果按照D->B->A->C的顺序将会调用A.method(),按照D->B->C->A的顺序将会调用C.method()。下面来研究一下Python的MRO,到底是如何进行的。

Python有如下的MRO:Python 2.2以前的经典类

Python 2.2中的新式类

Python 2.3及其以后新式类的C3 算法,Python 3 唯一支持的形式

经典类中的MRO

经典类的新式类的不同之处在于,新式类继承自object,在python 2.1及以前只有经典类,经典类的MRO采取自左向右的深度遍历,在上述钻石继承中,MRO顺序为D->B->A->C->A,去除重复结果:D->B->A->C,在经典类中D.method()调用的是A.method()。但是如果有这样一个问题,C.method()在A.method()基础上增加了新的功能(比如重写了这些属性或者方法),那么使用D.method()无法调用到C.method()。

import inspect

class A:

def method(self):

print 'This is a method of A'

class B(A):

pass

class C(A):

def method(self):

print 'This is a method of C'

class D(B, C):

pass

x = D()

x.method()

print inspect.getmro(D)

Python 2.2中的新式类MRO

对于新式类,所有类都要继承obejct,需要在创建类时继承object,同时可以使用__mro__查看MRO,对于新式类的MRO,将是自左向右的广度遍历,上述钻石继承的顺序就变成了D->B->C->A->object,解决了钻石继承在经典类中存在的问题。但是对于正常的继承关系:

class A(object):

pass

class B(object):

pass

class C(A):

pass

class D(B):

pass

class E(C, D):

pass

根据新式类中的广度遍历原则,E->C->D->A->B->object,A是C的唯一基类,但却在C之后先查询D,根据单调性,应该先从唯一基类进行查找。注意:在Python 2.2及其以后的版本仍然存在经典类,在定义基类时,如果继承object才是新式类,否则是经典类,注意下面两段代码以及运行结果的区别。Python 2中的经典类Python 2中的新式类

Python 2.3及其以后的新式类MRO

在Python 2.3及其以后的版本中,新式类的MRO使用C3算法,并且在Python 3中只存在新式类。Python 2.3及其以后的新式类MRO,使用的是拓扑排序,在一个有向无环图中:选择一个入度为0的顶点并输出(入度:以某顶点为弧头,终止于该顶点的弧的数目)

从网中删除此顶点以及所有出边

重复步骤1、2,直到所有点都被遍历

class A(object):

pass

class B(object):

pass

class C(object):

pass

class D(A, C):

pass

class E(B, A):

pass

class F(D, E):

pass

对于上图,使用C3算法得到的结果是:

(, , , , , , )

对于上述正常继承与钻石继承的结果分别如下:

(, , , , , )

(, , , , )

C3算法很好地解决了钻石继承在经典类中存在的问题,以及正常继承在Python 2.2新式类中存在的问题。留一个思考题,在C3算法下,下面的代码会输出什么以及MRO顺序:

class A(object):

def __init__(self):

print('enter A')

print('leave A')

class B(object):

def __init__(self):

print('enter B')

print('leave B')

class C(A):

def __init__(self):

print('enter C')

super(C, self).__init__()

print('leave C')

class D(A):

def __init__(self):

print('enter D')

super(D, self).__init__()

print('leave D')

class E(B, C):

def __init__(self):

print('enter E')

super(E, self).__init__()

print('leave E')

class F(E, D):

def __init__(self):

print('enter F')

super(F, self).__init__()

print('leave F')

f = F()

print(F.__mro__)

揭晓答案:

参考:Python super() 函数​www.runoob.comhttps://blog.csdn.net/weixin_40907382/article/details/80277152​blog.csdn.net人类身份验证 - SegmentFault​segmentfault.comPython的方法解析顺序(MRO)[转] - morra - 博客园​www.cnblogs.compython--inspect模块 - 姚红 - 博客园​www.cnblogs.com人类身份验证 - SegmentFault​segmentfault.com

mro python_Python之super与MRO相关推荐

  1. Python高级——多继承问题(super与mro)

    多继承问题 1.单独调用父类: 一个子类同时继承自多个父类,又称菱形继承.钻石继承. 使用父类名.init(self)方式调用父类时: 例: class Parent(object):def __in ...

  2. mro python_用python实现MRO算法

    引子: 如图反映了python3中,几个类的继承关系和查找顺序.对于类A,其查找顺序为:A,B,E,C,F,D,G,(Object),这并不是一个简单的深度优先或广度优先的规律.那么这个顺序到底是如何 ...

  3. mro python_Python新式类的方法解析顺序MRO与Super

    新式类与经典类的方法解析顺序 MOR(方法解析顺序) 经典类:深度优先 DFS python3以前 新式类:广度优先 python2.2 新式类:广度优先的C3算法实现(拓扑排序) BFS pytho ...

  4. 多继承以及MRO顺序【super().的使用】

    多继承以及MRO顺序 1. 单独调用父类的方法 # coding=utf-8print("******多继承使用类名.__init__ 发生的状态******") class Pa ...

  5. pythonsupermro_Python高级编程之继承问题详解(super与mro)

    本文实例讲述了Python高级编程之继承问题.分享给大家供大家参考,具体如下: 多继承问题 1.单独调用父类: 一个子类同时继承自多个父类,又称菱形继承.钻石继承. 使用父类名.init(self)方 ...

  6. 继承,经典类与新式类的MRO,C3算法,super

    #继承 class JiaoFu:def qd(self):print("教父带你祈祷") class Fu:def msj(self):print("alex喜欢msj ...

  7. Python 之 super MRO (没有遇到过适用场景)

    WOW!!! 这里wow的是真尼玛绕且没看完, 好困呐,贴上网址,等自己英文好一点再看(https://rhettinger.wordpress.com/2011/05/26/super-consid ...

  8. Python面向对象中super用法与MRO机制

    1. 引言 最近在研究django rest_framework的源码,老是遇到super,搞得一团蒙,多番查看各路大神博客,总算明白了一点,今天做一点总结. 2. 为什么要用super 1)让代码维 ...

  9. python 多继承与super使用详解_Python super()方法、多继承以及MRO顺序

    仅供学习,转载请注明出处 单独调用父类的方法 需求:编写一个类,然后再写一个子类进行继承,使用子类去调用父类的方法1. 使用方法1打印: 胖子老板,来包槟榔. 那么先写一个胖子老板的父类,执行一下: ...

  10. python在多继承中子类调用某个父类的同名方法之 super讲解(mro机制)***

    目录 2.   钻石继承遇到的难题 3.   针对钻石问题各语言的解决方法 3.1. C++ 3.2. Java 3.3. Ruby 3.4. Python 4.   super的内核:mro 5.  ...

最新文章

  1. php 空间类元素引入_引入单元素模式
  2. 达摩院2021年十大科技趋势出炉:量子计算、脑机接口…
  3. 【转】EventBus 3.0使用详解
  4. 3.5.6 轮询访问介质访问控制
  5. matlab中sum函数
  6. JS -- Unexpected trailing comma
  7. 复制(Copying)
  8. sql开启mysql远程连接_CentOS系统中安装MySQL和开启MySQL远程访问的方法
  9. C#实现缩放和剪裁图片的方法示例
  10. 转:智能卡测试操作系统技术
  11. linux下iostat命令无效,linux iostat命令详解
  12. Javascript调试之console对象,它的一些小技巧你都知道吗?
  13. 10-C++远征之模板篇-学习笔记
  14. Unity2020.2中支持的C#8有什么新特性?
  15. 手机上怎么去掉a 标签中的img点击时的阴影?
  16. tomcat修改http长度限制_解决浏览器与服务器请求url长度限制
  17. 你手写过堵塞队列吗?
  18. ASP.NET网站部署详细步骤
  19. 一键制作低多边形海报效果教程
  20. 抖音 Android 包体积优化探索:资源二进制格式的极致精简

热门文章

  1. js Math.rander的用法
  2. 2018 Google IO大会来了
  3. Redis集群管理工具redis-trib
  4. 死链提交为什么不能提交 html文件,搜狗死链提交
  5. 分析算法泛化性能的有效工具:偏差——方差分解
  6. 玉品游戏java_整蛊游戏N合一(玉品)
  7. debian10上安装samba服务器
  8. 【MicroPython ESP32】超低功耗协处理器(ULP):睡眠模式示例详解
  9. 怎么找网页源文件位置_无法查看网页的源文件该怎么办?
  10. 路飞学城python电子书闲鱼_路飞学城-python开发集训-第一章之用户登录作业