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的更多相关文章

  1. [修]python普通继承方式和super继承方式

    [转]python普通继承方式和super继承方式 原文出自:http://www.360doc.com/content/13/0306/15/9934052_269664772.shtml 原文的错 ...

  2. python 类继承演示范例的代码

    把做工程过程重要的代码片段备份一次,下面的资料是关于python 类继承演示范例的代码. # a simple example of a class inheritance # tested with ...

  3. python 全栈开发,Day20(object类,继承与派生,super方法,钻石继承)

    先来讲一个例子 老师有生日,怎么组合呢? class Birthday: # 生日 def __init__(self,year,month,day): self.year = year self.m ...

  4. Python类继承(转发)

    目录 一.概述 二.类的继承 2.1 继承的定义 2.2 构造函数的继承 2.3 子类对父类方法的重写 三.类继承的事例 回到顶部 一.概述 面向对象编程 (OOP) 语言的一个主要功能就是“继承”. ...

  5. 第7.7节 案例详解:Python类继承机制

    本节实现一个类继承的小程序,下面一边结合代码一边介绍相关继承的知识.例子以车.汽车为例,车为父类.汽车为子类. 一.    定义父类Vehicle class Vehicle():    def __ ...

  6. python类继承

    面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过 继承 机制.继承完全可以理解成类之间的 类型和子类型 关系. 假设你想要写一个程序来记录学校之中的教师和学生情况.他们有一些 ...

  7. python 类 - 继承

    继承 什么是继承? 编写类时,并非总要从空白开始.如果要编写的类是另一个现成类的特殊版本,可使用继承. 一个类继承另一个类时,将自动获得另一个类的所有属性和方法.现有的类称为父类,而新类称为子类. 子 ...

  8. python类继承的重写和super

    给已经存在的类添加新的行为,继承是非常好的实现方式.但是如果要改变行为呢?比如在Python继承扩展内置类,我们的contact类只允许一个名字和一个邮箱,但是如果要对某些人增加电话号码呢?这里可以通 ...

  9. 【Python】python 普通继承方式和super继承方式

    Python中对象方法的定义很怪异,第一个参数一般都命名为self(相当于其它语言的this),用于传递对象本身,而在调用的时候则不必显式传递,系统会自动传递.举一个很常见的例子:>>&g ...

随机推荐

  1. Qt多工程多目录的编译案例

    源地址:http://blog.csdn.net/libaineu2004/article/details/23625441 写这篇文章的目的是为了让Qt像VC++那样,支持一个工程包含多个项目.即1 ...

  2. Paip.断点调试MYSQL存储过程跟函数的解决方案大法

    Paip.断点调试MYSQL存储过程跟函数的解决方案大法 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn ...

  3. SGU114-Telecasting station

    114. Telecasting station time limit per test: 0.5 sec. memory limit per test: 4096 KB Every city in ...

  4. WindowsPhone8中实现圆形图片的生成显示

    原文 WindowsPhone8中实现圆形图片的生成显示 很多软件中(比如QQ)用到了许多圆形图片,作为用户头像等等,原始图片往往是方形的,那么怎么样将方形的图片显示成圆形呢? 一种方法是当背景为固定 ...

  5. HDU 3584 三维树状数组

    三维树状数组模版.优化不动了. #include <set> #include <map> #include <stack> #include <cmath& ...

  6. Passenger/Nginx/Debian快速部署Rails

    安装所需的linux包 sudo apt-get install build-essential bison openssl libreadline6 libreadline6-dev curl gi ...

  7. eclipse3.2 汉化 汉化包下载

    1.首先去www.eclipse.org下载eclipse3.2   点击下载eclipse3.2 2.再去www.eclipse.org下载它的汉化包   请使用迅雷等下载工具下载汉化包 注意不同版 ...

  8. alv 列标题

    gs_fieldcat-reptext_ddic才是显示列标题的

  9. 与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder)

    原文:与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) [索引页][源码下载] 与众不同 windows p ...

  10. 14.2.5.4 Physical Structure of an InnoDB Index InnoDB Index 的物理结构

    14.2.5.4 Physical Structure of an InnoDB Index InnoDB Index 的物理结构 所有的InnoDB indexes 是B-trees ,index ...