内建类 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 搜索

最新文章

  1. 用EmEditor实现PDF转Word后的对齐排版
  2. 项目中angular js的接口url统一管理
  3. 85. Maximal Rectangle
  4. Xcode LaunchImage 载入界面大小设置
  5. [U3D 画起重机,绑脚本和控制它运动的基本操作]
  6. &ldquo;享受&rdquo;英语的快乐&mdash;我是如何学英语的
  7. Freemarker-数字默认格式化问题
  8. ZooKeeper -- 分布式开源协调服务
  9. custom activities
  10. fread遇到1A则读取停止,发现是1A是文件截止符
  11. 使用WCF Data Service 创建OData服务
  12. 10 分钟学会Linux常用 bash命令
  13. [Swift]LeetCode256.粉刷房子 $ Paint House
  14. SQL-记录创建篇-006
  15. GO入门——6. struct与方法
  16. Git直接拉取远程分支
  17. python--列表内建函数的方法
  18. Centos调整时间时区
  19. 在远程登陆的主机上通过命令行源码编译安装 GNU M4、autoconf、automake 等程序
  20. Firefox不能加载TinyMCE的问题

热门文章

  1. 【Soft-Margin Support Vector Machine】林轩田机器学习技术
  2. jQuery easyuI datagrid 多行编辑
  3. 【2017】KK English
  4. 剑指offer-从尾到头打印链表03
  5. shell文本处理工具总结
  6. 聊聊、AES 和 DES
  7. 深入理解CSS中的margin
  8. Python洗牌算法重写
  9. 【Android】实验8 SQLite数据库操作2016.5.12
  10. 【转发】Build Squid with SSL Bump and ICAP Client