侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

深入解析Python编程中super关键字的用法

Python  /  管理员 发布于 7年前   193

官方文档中关于super的定义说的不是很多,大致意思是返回一个代理对象让你能够调用一些继承过来的方法,查找的机制遵循mro规则,最常用的情况如下面这个例子所示:

class C(B):  def method(self, arg):    super(C, self).method(arg)

子类C重写了父类B中同名方法method,在重写的实现中通过super实例化的代理对象调用父类的同名方法。

super类的初始方法签名如下:

def __init__(self, type1, type2=None): # known special case of super.__init__    """    super(type, obj) -> bound super object; requires isinstance(obj, type)    super(type) -> unbound super object    super(type, type2) -> bound super object; requires issubclass(type2, type)    Typical use to call a cooperative superclass method:

除去self外接受一个或者或者两个参数,如同注释声明的一样,接受两个参数时返回的是绑定的super实例,省略第二个参数的时候返回的是未绑定的super对象。

一般情况下当调用继承的类方法或者静态方法时,并不需要绑定具体的实例,这个时候使用super(type, type2).some_method就能达到目的,当然super(type, obj)在这种情况下也能够使用,super对象有自定义实现的getattribute方法也能够处理。不过,后者一般用来调用实例方法,这样在查找方法的时候能够传入相应的实例,从而得到绑定的实例方法:

class A(object):  def __init__(self):    pass  @classmethod  def klass_meth(cls):    pass  @staticmethod  def static_meth():    pass  def test(self):    passclass B(A):  pass>>> b = B()>>> super(B, b).test<bound method B.test of <__main__.B object at 0x02DA3570>>>>> super(B, b).klass_meth<bound method type.klass_meth of <class '__main__.B'>>>>> super(B, b).static_meth<function static_meth at 0x02D9CC70>>>> super(B, B).test<unbound method B.test>>>> super(B, B).klass_meth<bound method type.klass_meth of <class '__main__.B'>>>>> super(B,B).satic_meth>>> super(B,B).static_meth<function static_meth at 0x02D9CC70>

初始化super对象的时候,传递的第二个参数其实是绑定的对象,第一个参感觉数可以粗暴地理解为标记查找的起点,比如上面例子中的情况:super(B, b).test就会在B.__mro__里面列出的除B本身的类中查找方法test,因为方法都是非数据描述符,在super对象的自定义getattribute里面实际上会转化成A.__dict['test'].__get__(b, B)。

super在很多地方都会用到,除了让程序不必hardcode指定类型让代码更加动态,还有其他一些具体必用的地方比如元类中使用super查找baseclass里面的new生成自定义的类型模板;在自定义getattribute的时候用来防止无限循环等等。

关于super建议读者将它与python的描述符一起来理解,因为super就实现了描述符的协议,是一个非数据描述符,能够帮助大家更好的理解super的使用和工作原理。

同时,有以下4个点值得大家注意:
1、单继承时super()和__init__()实现的功能是类似的

class Base(object):  def __init__(self):    print 'Base create'class childA(Base):  def __init__(self):    print 'creat A ',    Base.__init__(self)class childB(Base):  def __init__(self):    print 'creat B ',    super(childB, self).__init__()base = Base()a = childA()b = childB()

输出结果:

Base createcreat A Base createcreat B Base create


使用super()继承时不用显式引用基类。

2、super()只能用于新式类中

把基类改为旧式类,即不继承任何基类

class Base():  def __init__(self):    print 'Base create'

执行时,在初始化b时就会报错:

  super(childB, self).__init__()TypeError: must be type, not classobj

3、super不是父类,而是继承顺序的下一个类

    在多重继承时会涉及继承顺序,super()相当于返回继承顺序的下一个类,而不是父类,类似于这样的功能:

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

    mro()用来获得类的继承顺序。

例如:

class Base(object):  def __init__(self):    print 'Base create'class childA(Base):  def __init__(self):    print 'enter A '    # Base.__init__(self)    super(childA, self).__init__()    print 'leave A'class childB(Base):  def __init__(self):    print 'enter B '    # Base.__init__(self)    super(childB, self).__init__()    print 'leave B'class childC(childA, childB):  passc = childC()print c.__class__.__mro__

输入结果如下:

enter A enter B Base createleave Bleave A(<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)

    supder和父类没有关联,因此执行顺序是A ―> B―>―>Base

    执行过程相当于:初始化childC()时,先会去调用childA的构造方法中的 super(childA, self).__init__(), super(childA, self)返回当前类的继承顺序中childA后的一个类childB;然后再执行childB().__init()__,这样顺序执行下去。

    在多重继承里,如果把childA()中的 super(childA, self).__init__() 换成Base.__init__(self),在执行时,继承childA后就会直接跳到Base类里,而略过了childB:

enter A Base createleave A(<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)

 

    从super()方法可以看出,super()的第一个参数可以是继承链中任意一个类的名字,

    如果是本身就会依次继承下一个类;

    如果是继承链里之前的类便会无限递归下去;

    如果是继承链里之后的类便会忽略继承链汇总本身和传入类之间的类;

    比如将childA()中的super改为:super(childC, self).__init__(),程序就会无限递归下去。

    如:

 File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__()RuntimeError: maximum recursion depth exceeded while calling a Python object

4、super()可以避免重复调用

    如果childA基础Base, childB继承childA和Base,如果childB需要调用Base的__init__()方法时,就会导致__init__()被执行两次:

class Base(object):  def __init__(self):    print 'Base create'class childA(Base):  def __init__(self):    print 'enter A '    Base.__init__(self)    print 'leave A'class childB(childA, Base):  def __init__(self):    childA.__init__(self)    Base.__init__(self)b = childB()  Base的__init__()方法被执行了两次enter A Base createleave ABase create使用super()是可避免重复调用class Base(object):  def __init__(self):    print 'Base create'class childA(Base):  def __init__(self):    print 'enter A '    super(childA, self).__init__()    print 'leave A'class childB(childA, Base):  def __init__(self):    super(childB, self).__init__()b = childB()print b.__class__.mro()
enter A Base createleave A[<class '__main__.childB'>, <class '__main__.childA'>, <class '__main__.Base'>, <type 'object'>]

您可能感兴趣的文章:

  • Python中super函数用法实例分析
  • Python中super函数的用法
  • Python中super()函数简介及用法分享
  • Python编程中对super函数的正确理解和用法解析
  • Python中super的用法实例
  • Python中的super用法详解
  • python super的使用方法及实例详解


  • 上一条:
    Python的网络编程库Gevent的安装及使用技巧
    下一条:
    深入了解Python数据类型之列表
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客