Python 类继承,__bases__, __mro__, super
Python是面向?qū)ο蟮木幊陶Z(yǔ)言,也支持類(lèi)繼承。
>>> class Base:
... pass
...
>>> class Derived(Base):
... pass
??
這樣就定義了兩個(gè)類(lèi),Derived繼承了Base。issubclass(a,b)能夠測(cè)試?yán)^承關(guān)系:
>>> issubclass(Derived, Base)
True
??
在Python中,每一個(gè)類(lèi)有一個(gè)__bases__屬性,列出其基類(lèi)
>>> Derived.__bases__
(<class '__main__.Base'>,)
??
同C++,Python支持多重繼承;
>>> class Derived2(Derived,Base):
... pass
...
Derived2繼承了Derived和Base(實(shí)際中不會(huì)這么寫(xiě))
>>> 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{ ^  | 
能夠見(jiàn),C++并沒(méi)有限制書(shū)寫(xiě)順序。warning指示了Derrived2中不能訪(fǎng)問(wèn)Base
Derived2 d;
Base &b = d;
error: 'Base' is an ambiguous base of 'Derived2'
Base &b = d;
^
??
回到Python繼承,Derived2是Derived的子類(lèi),也是Base的子類(lèi)
>>> issubclass(Derived2, Base)
True
>>> issubclass(Derived2, Derived)
True
??
__bases__類(lèi)似于Javascript中Object對(duì)象的__proto__,是實(shí)現(xiàn)繼承的基礎(chǔ),不同在于:__bases__不可改動(dòng),并且__bases__是類(lèi)的屬性而不是對(duì)象屬性(Javascript是基于對(duì)象的語(yǔ)言);
??
>>> 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'>)
??
對(duì)象的__class__屬性指明了所屬類(lèi)型;
>>> [].__class__
<class 'list'>
>>> ().__class__
<class 'tuple'>
>>> 1.__class__
File "<stdin>", line 1
1.__class__
^
SyntaxError: invalid syntax
??
>>> type(1)
<class 'int'>
在Python中1,是對(duì)象還是基本類(lèi)型?
??
__mro__
__mro__給出了method resolution order,即解析方法調(diào)用的順序。
??
>>> Derived.__mro__
(<class '__main__.Derived'>, <class '__main__.Base'>, <class 'object'>)
>>> Derived2.__mro__
(<class '__main__.Derived2'>, <class '__main__.Derived'>, <class '__main__.Base'>, <class 'object'>)
??
看上去和__bases__相像,僅僅是最后面多了個(gè)<class 'object'>
??
super
super函數(shù)能夠用于調(diào)用父類(lèi)的方法,而后者可能被子類(lèi)覆蓋;類(lèi)似在java中的作用,但使用起來(lái)更復(fù)雜些。
>>> 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
代理對(duì)象并非類(lèi)層次中某個(gè)類(lèi)的實(shí)例!
??
結(jié)合多重繼承來(lái)理解下__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__)
執(zhí)行結(jié)果
|   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的運(yùn)行路徑和類(lèi)的__mro__列舉的類(lèi)順序吻合;而__mro__的順序能夠看作是深搜的結(jié)果
A
/ | \
B C D
\ / /
E /
\ /
F
class E(B, C)中,B和C不是基-派生類(lèi)關(guān)系,E.__mro__中B在C之前,須要注意;
??
多態(tài)
??
>>> class Base:
... def sayHello(self):
... print("Base says hello")
...
>>> class Derived(Base):
... pass
...
>>> d = Derived()
>>> d.sayHello()
Base says hello
Derived重寫(xiě)sayHello
>>> class Derived(Base):
... def sayHello(self):
... print("Derived says hello");
...
>>> d = Derived()
>>> d.sayHello()
Derived says hello
??
與參數(shù)默認(rèn)值結(jié)合(聯(lián)想起了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
??
看一下,在基類(lèi)構(gòu)造函數(shù)中調(diào)用被覆蓋方法的行為
>>> 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
可見(jiàn),行為類(lèi)似Java,調(diào)用了子類(lèi)的覆蓋方法;
??
總結(jié)
以上是生活随笔為你收集整理的Python 类继承,__bases__, __mro__, super的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: 米读极速版免费阅读
 - 下一篇: 后宫秘史手游在哪下载 2011年冯绍峰