日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python 类继承,__bases__, __mro__, super

發布時間:2023/12/31 python 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。