内建类 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. 常用模块(random)

    import randomimport string# dt = random.randint(1,2) # 从1-2间取随机数,包括1.2# dt = random.randrange(1,3) # ...

  2. springboot整合jersey

    https://blog.csdn.net/xiongpei00/article/details/76576420

  3. 抽象类和虚方法、base关键字

    微软官方文档:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/abstract ...

  4. python使用工具简介介绍

    我从研究生开学以来就开始在学python,现在来简单分享下一些基本的使用命令和快捷方式 Pycharm: 运行程序 ctrl+alt+F10 删除一行ctrl+D 注释ctrl+/ 安装python所 ...

  5. linux configuration

    sudo vi /etc/profile export JAVA_HOME=/usr/bin/jdk1.8.0_40export JRE_HOME=${JAVA_HOME}/jre  export C ...

  6. 【距离GDKOI:44天&GDOI:107天】【BZOJ1040】[ZJOI2008] 骑士 (环套树DP)

    其实已经准备退役了,但GDOI之前还是会继续学下去的!!当成兴趣在学,已经对竞赛失去信心了的样子,我还是回去跪跪文化课吧QAQ 第一道环套树DP...其实思想挺简单的,就把环拆开,分类处理.若拆成开的 ...

  7. [BZOJ3600] 没有人的算术 [重量平衡树+权值线段树]

    题面 传送门 思路 这道题目是陈立杰论文<重量平衡树和后缀平衡树在信息学奥赛中的应用 >中关于重量平衡树维护序列排名算法的一个应用 具体方法为:令根节点保存一个实数区间$[0,1]$ 若当 ...

  8. 实时流处理Storm、Spark Streaming、Samza、Flink孰优孰劣

    对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在不断的升级改进,从0.8.x版本开始到现在的1.1.x版本,Kafka的 ...

  9. [bzoj] 1036 Count

    原题 树链剖分板子题 树剖详解: #include<cstdio> #include<algorithm> typedef long long ll; #define N 30 ...

  10. 【CZY选讲·次大公因数】

    题目描述 给定n个数ai,求sgcd(a1,a1),sgcd(a1,a2),…,sgcd(a1,an). 其中sgcd(x,y)表示x和y的次大公因数.若不存在次大公因数,sgcd(x,y)=-1 ...