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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python多继承顺序_Python多继承以及MRO顺序的使用

發(fā)布時(shí)間:2024/9/27 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python多继承顺序_Python多继承以及MRO顺序的使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

多繼承以及MRO順序

1. 單獨(dú)調(diào)用父類的方法

# coding=utf-8

print("******多繼承使用類名.__init__ 發(fā)生的狀態(tài)******")

class Parent(object):

def __init__(self, name):

print('parent的init開始被調(diào)用')

self.name = name

print('parent的init結(jié)束被調(diào)用')

class Son1(Parent):

def __init__(self, name, age):

print('Son1的init開始被調(diào)用')

self.age = age

Parent.__init__(self, name)

print('Son1的init結(jié)束被調(diào)用')

class Son2(Parent):

def __init__(self, name, gender):

print('Son2的init開始被調(diào)用')

self.gender = gender

Parent.__init__(self, name)

print('Son2的init結(jié)束被調(diào)用')

class Grandson(Son1, Son2):

def __init__(self, name, age, gender):

print('Grandson的init開始被調(diào)用')

Son1.__init__(self, name, age) # 單獨(dú)調(diào)用父類的初始化方法

Son2.__init__(self, name, gender)

print('Grandson的init結(jié)束被調(diào)用')

gs = Grandson('grandson', 12, '男')

print('姓名:', gs.name)

print('年齡:', gs.age)

print('性別:', gs.gender)

print("******多繼承使用類名.__init__ 發(fā)生的狀態(tài)******\n\n")

運(yùn)行結(jié)果:

******多繼承使用類名.__init__ 發(fā)生的狀態(tài)******

Grandson的init開始被調(diào)用

Son1的init開始被調(diào)用

parent的init開始被調(diào)用

parent的init結(jié)束被調(diào)用

Son1的init結(jié)束被調(diào)用

Son2的init開始被調(diào)用

parent的init開始被調(diào)用

parent的init結(jié)束被調(diào)用

Son2的init結(jié)束被調(diào)用

Grandson的init結(jié)束被調(diào)用

姓名: grandson

年齡: 12

性別: 男

******多繼承使用類名.__init__ 發(fā)生的狀態(tài)******

2. 多繼承中super調(diào)用有所父類的被重寫的方法

print("******多繼承使用super().__init__ 發(fā)生的狀態(tài)******")

class Parent(object):

def __init__(self, name, *args, **kwargs): # 為避免多繼承報(bào)錯(cuò),使用不定長(zhǎng)參數(shù),接受參數(shù)

print('parent的init開始被調(diào)用')

self.name = name

print('parent的init結(jié)束被調(diào)用')

class Son1(Parent):

def __init__(self, name, age, *args, **kwargs): # 為避免多繼承報(bào)錯(cuò),使用不定長(zhǎng)參數(shù),接受參數(shù)

print('Son1的init開始被調(diào)用')

self.age = age

super().__init__(name, *args, **kwargs) # 為避免多繼承報(bào)錯(cuò),使用不定長(zhǎng)參數(shù),接受參數(shù)

print('Son1的init結(jié)束被調(diào)用')

class Son2(Parent):

def __init__(self, name, gender, *args, **kwargs): # 為避免多繼承報(bào)錯(cuò),使用不定長(zhǎng)參數(shù),接受參數(shù)

print('Son2的init開始被調(diào)用')

self.gender = gender

super().__init__(name, *args, **kwargs) # 為避免多繼承報(bào)錯(cuò),使用不定長(zhǎng)參數(shù),接受參數(shù)

print('Son2的init結(jié)束被調(diào)用')

class Grandson(Son1, Son2):

def __init__(self, name, age, gender):

print('Grandson的init開始被調(diào)用')

# 多繼承時(shí),相對(duì)于使用類名.__init__方法,要把每個(gè)父類全部寫一遍

# 而super只用一句話,執(zhí)行了全部父類的方法,這也是為何多繼承需要全部傳參的一個(gè)原因

# super(Grandson, self).__init__(name, age, gender)

super().__init__(name, age, gender)

print('Grandson的init結(jié)束被調(diào)用')

print(Grandson.__mro__)

gs = Grandson('grandson', 12, '男')

print('姓名:', gs.name)

print('年齡:', gs.age)

print('性別:', gs.gender)

print("******多繼承使用super().__init__ 發(fā)生的狀態(tài)******\n\n")

運(yùn)行結(jié)果:

******多繼承使用super().__init__ 發(fā)生的狀態(tài)******

(, , , , )

Grandson的init開始被調(diào)用

Son1的init開始被調(diào)用

Son2的init開始被調(diào)用

parent的init開始被調(diào)用

parent的init結(jié)束被調(diào)用

Son2的init結(jié)束被調(diào)用

Son1的init結(jié)束被調(diào)用

Grandson的init結(jié)束被調(diào)用

姓名: grandson

年齡: 12

性別: 男

******多繼承使用super().__init__ 發(fā)生的狀態(tài)******

注意:

1. 以上2個(gè)代碼執(zhí)行的結(jié)果不同

2. 如果2個(gè)子類中都繼承了父類,當(dāng)在子類中通過父類名調(diào)用時(shí),parent被執(zhí)行了2次

3. 如果2個(gè)子類中都繼承了父類,當(dāng)在子類中通過super調(diào)用時(shí),parent被執(zhí)行了1次

3. 單繼承中super

print("******單繼承使用super().__init__ 發(fā)生的狀態(tài)******")

class Parent(object):

def __init__(self, name):

print('parent的init開始被調(diào)用')

self.name = name

print('parent的init結(jié)束被調(diào)用')

class Son1(Parent):

def __init__(self, name, age):

print('Son1的init開始被調(diào)用')

self.age = age

super().__init__(name) # 單繼承不能提供全部參數(shù)

print('Son1的init結(jié)束被調(diào)用')

class Grandson(Son1):

def __init__(self, name, age, gender):

print('Grandson的init開始被調(diào)用')

super().__init__(name, age) # 單繼承不能提供全部參數(shù)

print('Grandson的init結(jié)束被調(diào)用')

gs = Grandson('grandson', 12, '男')

print('姓名:', gs.name)

print('年齡:', gs.age)

#print('性別:', gs.gender)

print("******單繼承使用super().__init__ 發(fā)生的狀態(tài)******\n\n")

總結(jié)

super().__init__相對(duì)于類名.init,在單繼承上用法基本無(wú)差

但在多繼承上有區(qū)別,super方法能保證每個(gè)父類的方法只會(huì)執(zhí)行一次,而使用類名的方法會(huì)導(dǎo)致方法被執(zhí)行多次,具體看前面的輸出結(jié)果

多繼承時(shí),使用super方法,對(duì)父類的傳參數(shù),應(yīng)該是由于python中super的算法導(dǎo)致的原因,必須把參數(shù)全部傳遞,否則會(huì)報(bào)錯(cuò)

單繼承時(shí),使用super方法,則不能全部傳遞,只能傳父類方法所需的參數(shù),否則會(huì)報(bào)錯(cuò)

多繼承時(shí),相對(duì)于使用類名.__init__方法,要把每個(gè)父類全部寫一遍,

而使用super方法,只需寫一句話便執(zhí)行了全部父類的方法,這也是為何多繼承需要全部傳參的一個(gè)原因

小試牛刀(以下為面試題)

以下的代碼的輸出將是什么? 說出你的答案并解釋。

class Parent(object):

x = 1

class Child1(Parent):

pass

class Child2(Parent):

pass

print(Parent.x, Child1.x, Child2.x)

Child1.x = 2

print(Parent.x, Child1.x, Child2.x)

Parent.x = 3

print(Parent.x, Child1.x, Child2.x)

答案, 以上代碼的輸出是:

使你困惑或是驚奇的是關(guān)于最后一行的輸出是 3 2 3 而不是 3 2 1。為什么改變了 Parent.x 的值還會(huì)改變 Child2.x

的值,但是同時(shí) Child1.x 值卻沒有改變?

這個(gè)答案的關(guān)鍵是,在 Python中,類變量在內(nèi)部是作為字典處理的。如果一個(gè)變量的名字沒有在當(dāng)前類的字典中發(fā)現(xiàn),將搜索祖先類(比如父類)直到被引用的變量名被找到(如果這個(gè)被引用的變量名既沒有在自己所在的類又沒有在祖先類中找到,會(huì)引發(fā)一個(gè) AttributeError 異常 )。

因此,在父類中設(shè)置 x = 1 會(huì)使得類變量 x 在引用該類和其任何子類中的值為 1。這就是因?yàn)榈谝粋€(gè) print 語(yǔ)句的輸出是 1 1 1。

隨后,如果任何它的子類重寫了該值(例如,我們執(zhí)行語(yǔ)句 Child1.x = 2),然后,該值僅僅在子類中被改變。這就是為什么第二個(gè)print 語(yǔ)句的輸出是 1 2 1。

最后,如果該值在父類中被改變(例如,我們執(zhí)行語(yǔ)句 Parent.x =

3),這個(gè)改變會(huì)影響到任何未重寫該值的子類當(dāng)中的值(在這個(gè)示例中被影響的子類是 Child2)。這就是為什么第三個(gè) print 輸出是 3 2 3。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

總結(jié)

以上是生活随笔為你收集整理的python多继承顺序_Python多继承以及MRO顺序的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。