内建类 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. DOS程序员手册(二)

    2.6存储设备     随着DOS的升级,磁盘存储容量也有了很大扩充.表2.4介绍了软盘容量的增加以     及所支持驱动器型号的数量.                                 ...

  2. linux运维笔记

    一.查找大文件 sudo find / -size +100M -exec ls -lh {} \;

  3. GLIBCXX3.4.21 not find

    在执行世界杯的二进制代码和安装keepaway中会遇到GLIBCXX3.4.21 not find的问题,其解决办法就是升级安装GCC. 一.首先查看当前gcc版本 $ strings /usr/li ...

  4. sql 游标使用

    declare @PASSDate datetime,@VLPN varchar(50),@VLPNColor varchar(10),@nambers int set @VLPN='';set @V ...

  5. System.Activator类

    public static ObjectHandle CreateInstance(string assemblyName, string typeName); 该类有一个方法. // // 摘要: ...

  6. 写把proto函数搞清楚

    在做blk层之前,先把proto搞清楚 ffi_lua metatype可以给函数加方法, lua中冒号是啥意思?冒号会传入self,但是点号不会传入self

  7. Angular & RxJS & Typesc­ript

    Angular & RxJS & Typesc­ript https://www.wmnetwork.cc/d/?mid=75627 杭州经开区国际创博中心 https://www.w ...

  8. BZOJ 1912:[Apio2010]patrol 巡逻(树直径)

    1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ ...

  9. Codeforces Round #387 (Div. 2) 747E

    这题本身是个水题,但是写了半天 题意就是给出一个树的生成方式,让你还原这棵树,然后按深度输出结点 这个还原过程还是比较有趣的(没有用递归) PS:getline的新姿势get #include < ...

  10. 设置RobotFramework的ftplibrary中,将Upload_file操作的异常改为回显错误信息。

    测试中需要通过FTP通道,将数据发送给服务器,而这个上传的数据要被阻断.在结合RobotFramework测试中,安装的ftplibrary,使用upload_file操作,如果上传动作失败,会抛出异 ...