Python的程序结构[2] -> 类/Class[4] -> 内建类 super
内建类 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 为其他基类的时候,只需要做出很小的修改。
Super的MRO & 传参
下面的例子显示了带参数的方法使用 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的更多相关文章
- Python的程序结构[5] -> 模块/Module[0] -> 内建模块 builtins
builtins 内建模块 / builtins Module 在Python的模块中,有一种特殊模块,无需导入便可以使用,其中包含了许多内建函数与类. builtins 模块内容 / builtin ...
- Python的程序结构[2] -> 类/Class[3] -> 内建类与内建函数
内建类与内建函数的区分 / Distinction of Built-in Type and Function 对于 Python,有许多可以不需要定义或引用就可以使用的函数(类)(参考内建模块),诸 ...
- Python的程序结构[2] -> 类/Class[5] -> 内建类 bytes 和 bytearray
内建类 bytes 和 bytearray / Built-in Type bytes and bytearray 关于内建类 Python的内建类 bytes 主要有以下几点: class byte ...
- Python的程序结构[2] -> 类/Class[6] -> 内建类 map
内建类map / Built-in Type map 关于内建类 map 是一个内建的类,能够返回一个 map 的 obj.map 的第一个参数为一个可执行函数,后续参数均为可迭代对象,map 会分别 ...
- [ActionScript3.0] 为内建类添加方法
通过使用prototype在继承内建类特性的同时加入新方法 Array.prototype.removeElement = function (item:*):void { var index:int ...
- Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法
类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...
- Python的程序结构[2] -> 类/Class[0] -> 类的特殊属性
类的特殊属性 / Special Property of Class Python 中通过 class 进行类的定义,类可以实例化成实例并利用实例对方法进行调用. 类中还包含的一些共有的特殊属性. 特 ...
- Python的程序结构[2] -> 类/Class[1] -> 基类与继承
基类与继承 / Base Class and Inheritance Class 面向对象的特性使得 Python 中不可避免地需要使用到类和类的继承,类的继承可以使得代码很好的被重用.下面以一些代码 ...
- Python的程序结构[2] -> 类/Class[2] -> 方法解析顺序 MRO
方法解析顺序 / MRO (Method Resolution Order) 关于方法解析顺序(MRO)的详细内容可以参考文末链接,这里主要对 MRO 进行简要的总结说明以及一些练习示例. 经典类和新 ...
随机推荐
- 使用原生node写一个聊天室
在学习node的时候都会练习做一个聊天室的项目,主要使用socket.io模块和http模块.这里我们使用更加原始的方式去写一个在命令行聊天的聊天室. http模块,socket.io都是高度封装之后 ...
- RAID介绍和实现
RAID的全称是廉价磁盘冗余阵列(Redundant Array of Inexpensive Disks),于1987年由美国Berkeley 大学的两名工程师提出的. RAID出现的,最初目的是将 ...
- vue cli & npm err & shit cnpm
vue cli & npm err & shit cnpm npm err & shit cnpm https://github.com/vuejs/vue-cli/issue ...
- MyBatis 基本演示
主配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration P ...
- BZOJ4894 天赋 【矩阵树定理】
题目链接 BZOJ4894 题解 双倍经验P5297 题解 #include<iostream> #include<cstring> #include<cstdio> ...
- BZOJ1821 [JSOI2010]Group 部落划分 Group 【最小生成树】
题目 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗.只是,这一切都成为谜团了--聪聪根 ...
- 如何用cookie保存用户的登录的密码和用户名
思路:绘制一个简单的登录界面的Servlet并要在此页面中读取保存密码和用户名的cookie--->在登录处理界面的servlet中把用户名和密码保存到cookie中 //登录界面的Servle ...
- 从日升的mecha anime看mecha genre的衰退
注:矢立肇是日升企画部集体笔名,如勇者系列便是公司企画 这里列出一些我看过认为有意思的动画,大抵同系列的就合并了,除非后续作品(剧场版,OVA,etc)并非直接剧情承接且有趣 注意我对长篇TV动画评价 ...
- Windows 2008 R2无法打补丁
遇到了Windows 2008 R2无法打补丁,并且控制台上的feature和roles都是error 可下载这个补丁进行修复: System Update Readiness Tool for Wi ...
- Hibernate中inverse="true"的理解
Hibernate中inverse="true"的理解 举例如下 转自:http://lijiejava.iteye.com/blog/776587 Customer类: publ ...