内建类 super / Built-in Type super


关于内建类

对于 super 可以从官方文档中看到基本介绍,super 接收一个类,以及类或类的实例,最终返回一个代理对象的实例。而 MRO 搜索也将被用在 super(同 getattr)上,因此 super 调用的不一定是父类的方法,而有可能是 sibling 的方法。还有一点值得注意的是,当传入的第二个参数被省略时,则返回的 super 对象未绑定,若有第二个参数,则第二个参数必须是第一个参数的实例或子类。官方文档对于 super 的定义如下,

super([type[, object-or-type]])

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.

The __mro__ attribute of the type lists the method resolution search order used by both getattr() and super(). The attribute is dynamic and can change whenever the inheritance hierarchy is updated.

If the second argument is omitted, the super object returned is unbound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true (this is useful for classmethods).

下面给出super的使用例子。

Super的使用


首先定义一个基类 A 以及 show 方法,然后定义一个 B 继承自 A,在初始化中,使用 super 获得一个代理并调用初始化函数。

而当需要从 B 的 show 方法中调用 A 的 show 方法时,同样可以使用 super 来完成,同时 super 还具有两种写法,其功能都相同。

 class A:
def __init__(self):
pass def show(self):
print("This is A.") class B(A):
def __init__(self):
super(B, self).__init__()
print(super(B, self)) def show(self):
print("This is B.")
super(B, self).show()
super().show() b = B()
b.show()

从输出的结果中可以看到,虽然在 B 中重载了 show 方法,但依旧可以通过 super 来调用这个被子类覆盖的方法。

<super: <class 'B'>, <B object>>
This is B.
This is A.
This is A.

由于 super 返回的是一个代理类,也就是说可以将其利用类属性保存下来使用,虽然这么做有些奇怪,但是却是可行的。

 class C(A):
def __init__(self):
self.a = super(C, self)
print(self.a) def show(self):
print("This is C.")
self.a.show() c = C()
c.show()

最终显示结果如下,与每次 super 调用相同。

<super: <class 'C'>, <C object>>
This is C.
This is A.

最值得注意的一点在于,在 super 的使用过程中,不涉及任何关于父类 A 的传入,而当 A 被修改后,相应的 super 代理也会变化。这样在替换基类 A 为其他基类的时候,只需要做出很小的修改。

SuperMRO & 传参


下面的例子显示了带参数的方法使用 super 进行调用的使用方式,以及一个 MRO 搜索顺序的验证。

首先定义一个菱形继承 ABCD,此时最值得注意的是 B 类的 super 调用,此时 B 的基类是 A,但是 B 的 super 调用的却是类 C 的初始化函数,这是由于 MRO 的搜索规则所决定的。

 class A:
def __init__(self, name):
print("A init.")
self.name = name class B(A):
def __init__(self, age):
print("B init.")
self.age = age
super(B, self).__init__("LIKE") # This super() will call C.__init__() class C(A):
def __init__(self, age):
print("C init.")
self.age = age
super(C, self).__init__("like") class D(B, C):
def __init__(self):
print("D init.")
super(D, self).__init__(7) d = D()
print(d.__dict__)

从输出的结果中可以看到,super 的调用符合 MRO,最终 d 的属性也可以验证,B 类初始化中的 super 调用的是 C 的初始化函数,因此 super 并不能简单的理解为调用父类方法。

D init.
B init.
C init.
A init.
{'age': 'LIKE', 'name': 'like'}

相关阅读


1. 关于内建类

2. MRO 搜索

Python的程序结构[2] -> 类/Class[4] -> 内建类 super的更多相关文章

  1. Python的程序结构[5] -> 模块/Module[0] -> 内建模块 builtins

    builtins 内建模块 / builtins Module 在Python的模块中,有一种特殊模块,无需导入便可以使用,其中包含了许多内建函数与类. builtins 模块内容 / builtin ...

  2. Python的程序结构[2] -> 类/Class[3] -> 内建类与内建函数

    内建类与内建函数的区分 / Distinction of Built-in Type and Function 对于 Python,有许多可以不需要定义或引用就可以使用的函数(类)(参考内建模块),诸 ...

  3. Python的程序结构[2] -> 类/Class[5] -> 内建类 bytes 和 bytearray

    内建类 bytes 和 bytearray / Built-in Type bytes and bytearray 关于内建类 Python的内建类 bytes 主要有以下几点: class byte ...

  4. Python的程序结构[2] -> 类/Class[6] -> 内建类 map

    内建类map / Built-in Type map 关于内建类 map 是一个内建的类,能够返回一个 map 的 obj.map 的第一个参数为一个可执行函数,后续参数均为可迭代对象,map 会分别 ...

  5. [ActionScript3.0] 为内建类添加方法

    通过使用prototype在继承内建类特性的同时加入新方法 Array.prototype.removeElement = function (item:*):void { var index:int ...

  6. Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法

    类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...

  7. Python的程序结构[2] -> 类/Class[0] -> 类的特殊属性

    类的特殊属性 / Special Property of Class Python 中通过 class 进行类的定义,类可以实例化成实例并利用实例对方法进行调用. 类中还包含的一些共有的特殊属性. 特 ...

  8. Python的程序结构[2] -> 类/Class[1] -> 基类与继承

    基类与继承 / Base Class and Inheritance Class 面向对象的特性使得 Python 中不可避免地需要使用到类和类的继承,类的继承可以使得代码很好的被重用.下面以一些代码 ...

  9. Python的程序结构[2] -> 类/Class[2] -> 方法解析顺序 MRO

    方法解析顺序 / MRO (Method Resolution Order) 关于方法解析顺序(MRO)的详细内容可以参考文末链接,这里主要对 MRO 进行简要的总结说明以及一些练习示例. 经典类和新 ...

随机推荐

  1. nodejs 操作mongodb, 增删改查

    很久没有学node了,之前书看了一半,今天继续学发现版本问题很坑爹,按书例子执行一堆错误.想学nodejs操作db,百度半天,一堆sb写神马鸟玩儿?简简单单写一大堆还运行不了的.需要代码也是看别人写的 ...

  2. Ajax异步与JavaScript的一些初浅认识

    向服务器请求数据的技术 有以下五种常用技术用于向服务器请求数据 XMLHttpRequest(XHR) Dynamic script tag insertion(动态脚本标签插入) iframes C ...

  3. Jmeter 场景设计

    今天的业务场景是: 1.管理员登录后台---登录成功后添加一个某类型的产品---产品添加成功后,再为该产品添加10个排期. 2.管理员登录后台--登录成功后添加多个不同类型产品---产品全部添加完成后 ...

  4. Java基础-7数组

    一).什么是数组: 数组是一组具有相同类型和名称的变量集合,把一系列相同类型的数据保存在一起,这些变量称为数组的元素:每个元素都有一个编号,这个编号叫做下标,下标从 0 开始:元素的个数被称为数组的长 ...

  5. Python全栈 MySQL 数据库 (引擎、事物、pymysql模块、orm)

    ParisGabriel              每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰    开局一张图     存储引擎(处理表的处理器)     基本操作:         ...

  6. nyoj 题目49 开心的小明

    开心的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天 ...

  7. hadoop2.5.2学习及实践笔记(三)—— HDFS概念及体系结构

    注:文中涉及的文件路径或配置文件中属性名称是针对hadoop2.X系列,相对于之前版本,可能有改动. 附: HDFS用户指南官方介绍: http://hadoop.apache.org/docs/r2 ...

  8. Struts1 Spring2 iBatis2 框架的集成

    这个是属于比较老的框架了,奈何现在公司用的产品就是如此,闲来就搭一个集成框架吧 依赖jar包 antlr-.jar aspectj-.jar aspectjrt.jar aspectjweaver-. ...

  9. Struts1 生成Action请求的几种方式分析

    1 直接硬编码 <a href="/Lesson14_Struts1_Demo1//user/regUserDo.do">注册</a><br/> ...

  10. Codeforces Round #364 (Div. 1) 700B(树)

    题目大意 在n颗结点的树上有2k个需要配对的点,把他们两两配对,使得路程和最大并输出 选取一个点v lv表示v与父亲的边 那么考虑lv被经过的次数,对于一个最大的情况,lv应该为min(sv, 2*k ...