Python 类继承,__bases__, __mro__, super
Python是面向对象的编程语言,也支持类继承。
>>> class Base:
... pass
...
>>> class Derived(Base):
... pass
这样就定义了两个类,Derived继承了Base。issubclass(a,b)能够測试继承关系:
>>> issubclass(Derived, Base)
True
在Python中,每一个类有一个__bases__属性,列出其基类
>>> Derived.__bases__
(<class '__main__.Base'>,)
同C++,Python支持多重继承;
>>> class Derived2(Derived,Base):
... pass
...
Derived2继承了Derived和Base(实际中不会这么写)
>>> Derived2.__bases__
(<class '__main__.Derived'>, <class '__main__.Base'>)
这里,Derived,和Base的顺序不能搞反
>>> class Derived2(Base, Derived):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Cannot create a consistent method resolution
order (MRO) for bases Derived, Base
插一段C++
C++代码 |
class Base{ }; class Derived: public Base{ }; class Derived2: public Base, public Derived{ }; int main(){ } |
mulit_inherit.cc:7:7: warning: direct base 'Base' inaccessible in 'Derived2' due to ambiguity [enabled by default] class Derived2: public Base, public Derived{ ^ |
mulit_inherit.cc:7:7: warning: direct base 'Base' inaccessible in 'Derived2' due to ambiguity [enabled by default] class Derived2: public Derived, public Base{ ^ |
能够见,C++并没有限制书写顺序。warning指示了Derrived2中不能訪问Base
Derived2 d;
Base &b = d;
error: 'Base' is an ambiguous base of 'Derived2'
Base &b = d;
^
回到Python继承,Derived2是Derived的子类,也是Base的子类
>>> issubclass(Derived2, Base)
True
>>> issubclass(Derived2, Derived)
True
__bases__类似于Javascript中Object对象的__proto__,是实现继承的基础,不同在于:__bases__不可改动,并且__bases__是类的属性而不是对象属性(Javascript是基于对象的语言);
>>> d = Derived2()
>>> d.__bases__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Derived2' object has no attribute '__bases__'
>>> d.__class__
<class '__main__.Derived2'>
>>> d.__class__.__bases__
(<class '__main__.Derived'>, <class '__main__.Base'>)
对象的__class__属性指明了所属类型;
>>> [].__class__
<class 'list'>
>>> ().__class__
<class 'tuple'>
>>> 1.__class__
File "<stdin>", line 1
1.__class__
^
SyntaxError: invalid syntax
>>> type(1)
<class 'int'>
在Python中1,是对象还是基本类型?
__mro__
__mro__给出了method resolution order,即解析方法调用的顺序。
>>> Derived.__mro__
(<class '__main__.Derived'>, <class '__main__.Base'>, <class 'object'>)
>>> Derived2.__mro__
(<class '__main__.Derived2'>, <class '__main__.Derived'>, <class '__main__.Base'>, <class 'object'>)
看上去和__bases__相像,仅仅是最后面多了个<class 'object'>
super
super函数能够用于调用父类的方法,而后者可能被子类覆盖;类似在java中的作用,但使用起来更复杂些。
>>> class Base:
... pass
...
>>> class Derived(Base):
... pass
...
>>> class Derived2(Derived)
File "<stdin>", line 1
class Derived2(Derived)
^
SyntaxError: invalid syntax
>>> class Derived2(Derived):
... pass
...
>>> d = Derived2()
>>> super(Derived2, d)
<super: <class 'Derived2'>, <Derived2 object>>
>>> super(Derived, d)
<super: <class 'Derived'>, <Derived2 object>>
>>> super(Base, d)
<super: <class 'Base'>, <Derived2 object>>
參考https://docs.python.org/2/library/functions.html#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().
>>> isinstance(super(Base, d), Base)
False
>>> isinstance(super(Derived, d), Base)
False
代理对象并非类层次中某个类的实例!
结合多重继承来理解下__mro__和super
class A:
def __init__(self):
print('enter __init__@A')
super(A,self).__init__()
print('exit __init__@A')
class B(A):
def __init__(self):
print('enter __init__@B')
super(B,self).__init__()
print('exit __init__@B')
class C(A):
def __init__(self):
print('enter __init__@C')
super(C,self).__init__()
print('exit __init__@C')
class D(A):
def __init__(self):
print('enter __init__@D')
super(D,self).__init__()
print('exit __init__@D')
class E(B,C):
def __init__(self):
print('enter __init__@E')
super(E,self).__init__()
print('exit __init__@E')
class F(E,D):
def __init__(self):
print('enter __init__@F')
super(F,self).__init__()
print('exit __init__@F')
if __name__ == '__main__':
A()
print(A.__mro__)
B()
print(B.__mro__)
C()
print(C.__mro__)
D()
print(D.__mro__)
E()
print(E.__mro__)
F()
print(F.__mro__)
执行结果
enter __init__@A exit __init__@A (<class '__main__.A'>, <class 'object'>) enter __init__@B enter __init__@A exit __init__@A exit __init__@B (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>) enter __init__@C enter __init__@A exit __init__@A exit __init__@C (<class '__main__.C'>, <class '__main__.A'>, <class 'object'>) enter __init__@D enter __init__@A exit __init__@A exit __init__@D (<class '__main__.D'>, <class '__main__.A'>, <class 'object'>) enter __init__@E enter __init__@B enter __init__@C enter __init__@A exit __init__@A exit __init__@C exit __init__@B exit __init__@E (<class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) enter __init__@F enter __init__@E enter __init__@B enter __init__@C enter __init__@D enter __init__@A exit __init__@A exit __init__@D exit __init__@C exit __init__@B exit __init__@E exit __init__@F (<class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>) |
观察到,super的运行路径和类的__mro__列举的类顺序吻合;而__mro__的顺序能够看作是深搜的结果
A
/ | \
B C D
\ / /
E /
\ /
F
class E(B, C)中,B和C不是基-派生类关系,E.__mro__中B在C之前,须要注意;
多态
>>> class Base:
... def sayHello(self):
... print("Base says hello")
...
>>> class Derived(Base):
... pass
...
>>> d = Derived()
>>> d.sayHello()
Base says hello
Derived重写sayHello
>>> class Derived(Base):
... def sayHello(self):
... print("Derived says hello");
...
>>> d = Derived()
>>> d.sayHello()
Derived says hello
与參数默认值结合(联想起了C++)
>>> class Base:
... def sayHello(self, str="Base"):
... print("Base says: " + str)
...
>>> class Derived(Base):
... def sayHello(self, str="Derived"):
... print("Dervied says: " + str)
...
>>>
>>> d = Derived()
>>> d.sayHello()
Dervied says: Derived
>>> Base.sayHello(d)
Base says: Base
>>> super(Derived, d).sayHello()
Base says: Base
看一下,在基类构造函数中调用被覆盖方法的行为
>>> class Base:
... def sayHello(self):
... str = self.getStr()
... print("Base says: " + str)
... def getStr(self):
... return "Base"
...
>>> class Derived(Base):
... def getStr(self):
... return "Derived"
...
>>>
>>> d = Derived()
>>> d.sayHello()
Base says: Derived
>>> def Base_init(self):
... self.sayHello()
...
>>> Base.__init__ = Base_init
>>> d = Derived()
Base says: Derived
可见,行为类似Java,调用了子类的覆盖方法;
Python 类继承,__bases__, __mro__, super相关推荐
- Python类继承及super()函数
文章目录 Python中单类继承 普通类方法继承 初始化函数继承 Python中多类继承 Python中单类继承 Python是一门面向对象的编程语言,支持类继承.新的类称为子类(Subclass), ...
- python类继承实例_Python实现类继承实例
Python是一种解释型.面向对象.动态数据类型的高级程序设计语言,本文就举一例Python类继承的实例. 实例代码如下: #! /usr/bin/python # Filename: inherit ...
- python类继承实例_python类继承与子类实例初始化用法分析
这篇文章主要介绍了python类继承与子类实例初始化用法,实例分析了Python类的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下 [ 先贴参考书籍原文(中文英文对照)] __init__方法介 ...
- python 类继承方法_python类的继承、多继承及其常用魔术方法
继承 一个类可以派生出一个子类,这个子类可以使用父类的属性及方法,也可以在父类的基础上添加自己的独特属性或方法.属性和方法的继承的顺序是先从自己开始,找不到再去找父类,父类没有再找父类的父类,其尽头就 ...
- Python类继承对象
类声明从object继承有什么理由吗? 我刚刚找到了执行此操作的代码,但找不到很好的理由. class MyClass(object):# class code follows... #1楼 难学Py ...
- python类继承中构造方法_第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解...
第8.3节Python类的__init__方法深入剖析:构造方法与继承详解 一. 引言 上两节介绍了构造方法的语法及参数,说明了构造方法是Python的类创建实例后首先执行的方法,并说明如果类没 ...
- python 类继承 父类初始化_python之子类继承父类时进行初始化的一些问题
直接看代码: classPerson:def __init__(self): self.name= "jack" classStudent(Person):def __init__ ...
- python类继承返回值_python继承threading.Thread实现有返回值的子类实例
继承与threading.thread实现有返回值的子类mythread,废话不多说,大家直接看代码 import threading class mythread(threading.thread) ...
- 浅析python类继承(一)
面向对象编程 (OOP) 语言的一个主要功能就是"继承".继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展. 通过继承创建的新类 ...
最新文章
- 漫画:如何在数组中找到和为 “特定值” 的三个数?
- 网站推广浅析库克八亿年终奖的背后苹果公司如何展开企业的营销推广
- 用 Java 实现断点续传 (HTTP)
- Additive属性动画
- 决策树模型组合之随机森林与GBDT
- react native改变app的图标和名称
- iOS Hacker 越狱后开发和逆向工具准备
- log4net 日志框架的配置
- OpenShift Origin中的Kubernetes Spark运算符(第1部分)
- 全球呼吸机告急!医疗科技巨头美敦力“开源”设计图和源代码
- 感受McAfee.Secure.Internet.Gateway
- 收银系统 mysql数据库_解决哗啦啦收银系统数据库备份问题
- 关于wow游戏插件制作之前的几件事
- 信息系统项目管理师考试难?一次过备考经验分享给大家
- 算法设计与分析复习大纲
- Alienware-17-R4-630-1060-MacOS 笔记本双显卡 外星人黑苹果hackintosh 10.15
- python查火车票_Python实现12306火车票查询系统
- Java语言十五讲(第十四讲 容器框架二)
- 自动动态调整广告出价OCPC
- mysql jail_FreeNAS:如何在Jail里面安装软件?