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 [email protected]‘)

super(A,self).__init__()

print(‘exit [email protected]‘)

class B(A):

def __init__(self):

print(‘enter [email protected]‘)

super(B,self).__init__()

print(‘exit [email protected]‘)

class C(A):

def __init__(self):

print(‘enter [email protected]‘)

super(C,self).__init__()

print(‘exit [email protected]‘)

class D(A):

def __init__(self):

print(‘enter [email protected]‘)

super(D,self).__init__()

print(‘exit [email protected]‘)

class E(B,C):

def __init__(self):

print(‘enter [email protected]‘)

super(E,self).__init__()

print(‘exit [email protected]‘)

class F(E,D):

def __init__(self):

print(‘enter [email protected]‘)

super(F,self).__init__()

print(‘exit [email protected]‘)

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 [email protected]

exit [email protected]

(<class ‘__main__.A‘>, <class ‘object‘>)

enter [email protected]

enter [email protected]

exit [email protected]

exit [email protected]

(<class ‘__main__.B‘>, <class ‘__main__.A‘>, <class ‘object‘>)

enter [email protected]

enter [email protected]

exit [email protected]

exit [email protected]

(<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)

enter [email protected]

enter [email protected]

exit [email protected]

exit [email protected]

(<class ‘__main__.D‘>, <class ‘__main__.A‘>, <class ‘object‘>)

enter [email protected]

enter [email protected]

enter [email protected]

enter [email protected]

exit [email protected]

exit [email protected]

exit [email protected]

exit [email protected]

(<class ‘__main__.E‘>, <class ‘__main__.B‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)

enter [email protected]

enter [email protected]

enter [email protected]

enter [email protected]

enter [email protected]

enter [email protected]

exit [email protected]

exit [email protected]

exit [email protected]

exit [email protected]

exit [email protected]

exit [email protected]

(<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,调用了子类的覆盖方法;

时间: 2024-10-24 04:50:25

Python 类继承,__bases__, __mro__, super的相关文章

python类继承和组合

在python3中所有类默认继承object,凡是继承了object的类都成为新式类,以及该子类的子类Python3中所有的类都是新式类,没有集成object类的子类成为经典类(在Python2中没有集成object的类以及它的子类都是经典类 继承式用来创建新的类的一种方式,好处是减少重复代码 class People: def __init__(self,name,age): self.name=name self.age=age def walking(self): print('%s is

python 类继承

[转]http://www.cnblogs.com/mmix2009/p/3538663.html 1 #!/usr/bin/python 2 # Filename: inherit.py 3 4 class SchoolMember: 5 '''Represents any school member.''' 6 def __init__(self, name, age): 7 self.name = name 8 self.age = age 9 print'(Initialized Sch

python多继承

http://blog.csdn.net/pipisorry/article/details/46381341 There are two typical use cases forsuper: In a class hierarchy withsingle inheritance, super can be used to refer to parent classes withoutnaming them explicitly, thus making the code more maint

04 Python的继承、方法重写、super()类

继承 A类继承B类,A即可获得B类的全部公共属性和方法.格式如:class A(B): class Animal: def sleep(self): print("zZZ...") def eat(self): print("yamiyami...") def run(self): print("huchihuchi...") class Dog(Animal): #Dog类拥有sleep,eat,run,bark四个方法 def bark(se

python类中super()和__init__()的区别

本文和大家分享的主要是python开发中super()和__init__()的区别,希望通过本文的分享,对初学者学习这部分内容有所帮助. 1.单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(self): print 'Base create' class childA(Base): def __init__(self): print 'creat A ', Base.__init__(self) class chi

Python进阶-继承中的MRO与super

摘要本文讲述Python继承关系中如何通过super()调用"父类"方法,super(Type, CurrentClass)返回CurrentClass的MRO中Type的下一个类的代理:以及如何设计Python类以便正确初始化. 1. 单继承中父类方法调用 在继承中,调用父类方法是很有必要的.调用父类方法的场景有很多: 比如必须调用父类的构造方法__init__才能正确初始化父类实例属性,使得子类实例对象能够继承到父类实例对象的实例属性: 再如需要重写父类方法时,有时候没有必要完全摒

类继承super原理

super 原理 super 的工作原理如下: def super(cls, inst): mro = inst.__class__.mro() return mro[mro.index(cls) + 1] 其中,cls 代表类,inst 代表实例,上面的代码做了两件事: 获取 inst 的 MRO 列表 查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1] 当你使用 super(cls, inst) 时,Python 会在 inst 的 M

python之继承、抽象类、新式类和经典类

一.上节补充1.静态属性静态属性 : 类的属性,所有的对象共享这个变量 如果用对象名去修改类的静态属性:在对象的空间中又创建了一个属性,而不能修改类中属性的值 操作静态属性应该用类名来操作 例1:请你写一个类,能够统计一共实例化了多少个对象? class Foo: count = 0 def __init__(self): Foo.count += 1 f1 = Foo() print(f1.count) # 1 f2 = Foo() f3 = Foo() f4 = Foo() f5 = Foo

python 类 六:继承自动寻找父类

本系列博客(python 类) 的部分例子来自于 <<python 核心编程 第二版>> 前面我们谈到 python 继承,是可以引用父类的__init__方法的 ,并在此基础上添加子类自己的特殊的属性的设定,形成子类自己的__init__  构造函数. 在这种方法中,必须显示的指出父类的名字. #coding:utf-8 class p(object):     def __init__(self,nm):         self.name  = nm class c(p):