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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面向对象之继承与派生

發(fā)布時(shí)間:2023/12/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面向对象之继承与派生 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

閱讀目錄

  • 一 初識(shí)繼承
  • 二 繼承與抽象(先抽象再繼承)
  • 三 繼承與重用性
  • 四 派生
  • 五 組合與重用性
  • 六 接口與歸一化設(shè)計(jì)
  • 七 抽象類
  • 八?繼承實(shí)現(xiàn)的原理(可惡的菱形問題)
  • 九 子類中調(diào)用父類的方法

一 初識(shí)繼承

什么是繼承

繼承是一種創(chuàng)建新類的方式,新建的類可以繼承一個(gè)或多個(gè)父類(python支持多繼承),父類又可稱為基類或超類,新建的類稱為派生類或子類。

子類會(huì)“”遺傳”父類的屬性,從而解決代碼重用問題(比如練習(xí)7中Garen與Riven類有很多冗余的代碼)

python中類的繼承分為:單繼承和多繼承

class ParentClass1: #定義父類passclass ParentClass2: #定義父類passclass SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClasspassclass SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號(hào)分隔開多個(gè)繼承的類pass

查看繼承

>>> SubClass1.__bases__ #__base__只查看從左到右繼承的第一個(gè)子類,__bases__則是查看所有繼承的父類 (<class '__main__.ParentClass1'>,) >>> SubClass2.__bases__ (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

經(jīng)典類與新式類

1.只有在python2中才分新式類和經(jīng)典類,python3中統(tǒng)一都是新式類 2.在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經(jīng)典類 3.在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類 3.在python3中,無論是否繼承object,都默認(rèn)繼承object,即python3中所有類均為新式類 #關(guān)于新式類與經(jīng)典類的區(qū)別,我們稍后討論

提示:如果沒有指定基類,python的類會(huì)默認(rèn)繼承object類,object是所有python類的基類,它提供了一些常見方法(如__str__)的實(shí)現(xiàn)。

>>> ParentClass1.__bases__ (<class 'object'>,) >>> ParentClass2.__bases__ (<class 'object'>,)

二 繼承與抽象(先抽象再繼承)

繼承描述的是子類與父類之間的關(guān)系,是一種什么是什么的關(guān)系。要找出這種關(guān)系,必須先抽象再繼承

抽象即抽取類似或者說比較像的部分。

抽象分成兩個(gè)層次:?

1.將奧巴馬和梅西這倆對(duì)象比較像的部分抽取成類;?

2.將人,豬,狗這三個(gè)類比較像的部分抽取成父類。

抽象最主要的作用是劃分類別(可以隔離關(guān)注點(diǎn),降低復(fù)雜度)

?

繼承:是基于抽象的結(jié)果,通過編程語言去實(shí)現(xiàn)它,肯定是先經(jīng)歷抽象這個(gè)過程,才能通過繼承的方式去表達(dá)出抽象的結(jié)構(gòu)。

抽象只是分析和設(shè)計(jì)的過程中,一個(gè)動(dòng)作或者說一種技巧,通過抽象可以得到類

?

三 繼承與重用性

==========================第一部分 例如貓可以:喵喵叫、吃、喝、拉、撒狗可以:汪汪叫、吃、喝、拉、撒如果我們要分別為貓和狗創(chuàng)建一個(gè)類,那么就需要為 貓 和 狗 實(shí)現(xiàn)他們所有的功能,偽代碼如下:#貓和狗有大量相同的內(nèi)容 class 貓:def 喵喵叫(self):print '喵喵叫'def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do somethingclass 狗:def 汪汪叫(self):print '喵喵叫'def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do something==========================第二部分 上述代碼不難看出,吃、喝、拉、撒是貓和狗都具有的功能,而我們卻分別的貓和狗的類中編寫了兩次。如果使用 繼承 的思想,如下實(shí)現(xiàn):動(dòng)物:吃、喝、拉、撒貓:喵喵叫(貓繼承動(dòng)物的功能)狗:汪汪叫(狗繼承動(dòng)物的功能)偽代碼如下: class 動(dòng)物:def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do something# 在類后面括號(hào)中寫入另外一個(gè)類名,表示當(dāng)前類繼承另外一個(gè)類 class 貓(動(dòng)物):def 喵喵叫(self):print '喵喵叫'# 在類后面括號(hào)中寫入另外一個(gè)類名,表示當(dāng)前類繼承另外一個(gè)類 class 狗(動(dòng)物):def 汪汪叫(self):print '喵喵叫'==========================第三部分 #繼承的代碼實(shí)現(xiàn) class Animal:def eat(self):print("%s 吃 " %self.name)def drink(self):print ("%s 喝 " %self.name)def shit(self):print ("%s 拉 " %self.name)def pee(self):print ("%s 撒 " %self.name)class Cat(Animal):def __init__(self, name):self.name = nameself.breed = ''def cry(self):print('喵喵叫')class Dog(Animal):def __init__(self, name):self.name = nameself.breed=''def cry(self):print('汪汪叫')# ######### 執(zhí)行 ######### c1 = Cat('小白家的小黑貓') c1.eat()c2 = Cat('小黑的小白貓') c2.drink()d1 = Dog('胖子家的小瘦狗') d1.eat() 使用繼承來重用代碼比較好的例子

?在開發(fā)程序的過程中,如果我們定義了一個(gè)類A,然后又想新建立另外一個(gè)類B,但是類B的大部分內(nèi)容與類A的相同時(shí)

我們不可能從頭開始寫一個(gè)類B,這就用到了類的繼承的概念。

通過繼承的方式新建類B,讓B繼承A,B會(huì)‘遺傳’A的所有屬性(數(shù)據(jù)屬性和函數(shù)屬性),實(shí)現(xiàn)代碼重用

class Hero:def __init__(self,nickname,aggressivity,life_value):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valuedef move_forward(self):print('%s move forward' %self.nickname)def move_backward(self):print('%s move backward' %self.nickname)def move_left(self):print('%s move forward' %self.nickname)def move_right(self):print('%s move forward' %self.nickname)def attack(self,enemy):enemy.life_value-=self.aggressivity class Garen(Hero):passclass Riven(Hero):passg1=Garen('草叢倫',100,300) r1=Riven('銳雯雯',57,200)print(g1.life_value) r1.attack(g1) print(g1.life_value)''' 運(yùn)行結(jié)果 243 ''' View Code

提示:用已經(jīng)有的類建立一個(gè)新的類,這樣就重用了已經(jīng)有的軟件中的一部分設(shè)置大部分,大大生了編程工作量,這就是常說的軟件重用,不僅可以重用自己的類,也可以繼承別人的,比如標(biāo)準(zhǔn)庫,來定制新的數(shù)據(jù)類型,這樣就是大大縮短了軟件開發(fā)周期,對(duì)大型軟件開發(fā)來說,意義重大.

注意:像g1.life_value之類的屬性引用,會(huì)先從實(shí)例中找life_value然后去類中找,然后再去父類中找...直到最頂級(jí)的父類。

重點(diǎn)!!!:再看屬性查找

class Foo:def f1(self):print('Foo.f1')def f2(self):print('Foo.f2')self.f1()class Bar(Foo):def f1(self):print('Foo.f1')b=Bar() b.f2() View Code

四 派生

當(dāng)然子類也可以添加自己新的屬性或者在自己這里重新定義這些屬性(不會(huì)影響到父類),需要注意的是,一旦重新定義了自己的屬性且與父類重名,那么調(diào)用新增的屬性時(shí),就以自己為準(zhǔn)了。

class Riven(Hero):camp='Noxus'def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會(huì)影響父類print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname)

在子類中,新建的重名的函數(shù)屬性,在編輯函數(shù)內(nèi)功能的時(shí)候,有可能需要重用父類中重名的那個(gè)函數(shù)功能,應(yīng)該是用調(diào)用普通函數(shù)的方式,即:類名.func(),此時(shí)就與調(diào)用普通函數(shù)無異了,因此即便是self參數(shù)也要為其傳值

class Riven(Hero):camp='Noxus'def __init__(self,nickname,aggressivity,life_value,skin):Hero.__init__(self,nickname,aggressivity,life_value) #調(diào)用父類功能self.skin=skin #新屬性def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會(huì)影響父類Hero.attack(self,enemy) #調(diào)用功能print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname)r1=Riven('銳雯雯',57,200,'比基尼') r1.fly() print(r1.skin)''' 運(yùn)行結(jié)果 銳雯雯 is flying 比基尼'''

五 組合與重用性

軟件重用的重要方式除了繼承之外還有另外一種方式,即:組合

組合指的是,在一個(gè)類中以另外一個(gè)類的對(duì)象作為數(shù)據(jù)屬性,稱為類的組合

>>> class Equip: #武器裝備類 ... def fire(self): ... print('release Fire skill') ... >>> class Riven: #英雄Riven的類,一個(gè)英雄需要有裝備,因而需要組合Equip類 ... camp='Noxus' ... def __init__(self,nickname): ... self.nickname=nickname ... self.equip=Equip() #用Equip類產(chǎn)生一個(gè)裝備,賦值給實(shí)例的equip屬性 ... >>> r1=Riven('銳雯雯') >>> r1.equip.fire() #可以使用組合的類產(chǎn)生的對(duì)象所持有的方法 release Fire skill

?

組合與繼承都是有效地利用已有類的資源的重要方式。但是二者的概念和使用場景皆不同,

1.繼承的方式

通過繼承建立了派生類與基類之間的關(guān)系,它是一種'是'的關(guān)系,比如白馬是馬,人是動(dòng)物。

當(dāng)類之間有很多相同的功能,提取這些共同的功能做成基類,用繼承比較好,比如老師是人,學(xué)生是人

2.組合的方式

用組合的方式建立了類與組合的類之間的關(guān)系,它是一種‘有’的關(guān)系,比如教授有生日,教授教python和linux課程,教授有學(xué)生s1、s2、s3...

class People:def __init__(self,name,age,sex):self.name=nameself.age=ageself.sex=sexclass Course:def __init__(self,name,period,price):self.name=nameself.period=periodself.price=pricedef tell_info(self):print('<%s %s %s>' %(self.name,self.period,self.price))class Teacher(People):def __init__(self,name,age,sex,job_title):People.__init__(self,name,age,sex)self.job_title=job_titleself.course=[]self.students=[]class Student(People):def __init__(self,name,age,sex):People.__init__(self,name,age,sex)self.course=[]egon=Teacher('egon',18,'male','沙河霸道金牌講師') s1=Student('牛榴彈',18,'female')python=Course('python','3mons',3000.0) linux=Course('python','3mons',3000.0)#為老師egon和學(xué)生s1添加課程 egon.course.append(python) egon.course.append(linux) s1.course.append(python)#為老師egon添加學(xué)生s1 egon.students.append(s1)#使用 for obj in egon.course:obj.tell_info() 例子:繼承與組合

當(dāng)類之間有顯著不同,并且較小的類是較大的類所需要的組件時(shí),用組合比較好

六 接口與歸一化設(shè)計(jì)

1.什么是接口

=================第一部分:Java 語言中的接口很好的展現(xiàn)了接口的含義: IAnimal.java /* * Java的Interface接口的特征: * 1)是一組功能的集合,而不是一個(gè)功能 * 2)接口的功能用于交互,所有的功能都是public,即別的對(duì)象可操作 * 3)接口只定義函數(shù),但不涉及函數(shù)實(shí)現(xiàn) * 4)這些功能是相關(guān)的,都是動(dòng)物相關(guān)的功能,但光合作用就不適宜放到IAnimal里面了 */package com.oo.demo; public interface IAnimal {public void eat();public void run(); public void sleep(); public void speak(); }=================第二部分:Pig.java:豬”的類設(shè)計(jì),實(shí)現(xiàn)了IAnnimal接口 package com.oo.demo; public class Pig implements IAnimal{ //如下每個(gè)函數(shù)都需要詳細(xì)實(shí)現(xiàn)public void eat(){System.out.println("Pig like to eat grass");}public void run(){System.out.println("Pig run: front legs, back legs");}public void sleep(){System.out.println("Pig sleep 16 hours every day");}public void speak(){System.out.println("Pig can not speak"); } }=================第三部分:Person2.java /* *實(shí)現(xiàn)了IAnimal的“人”,有幾點(diǎn)說明一下: * 1)同樣都實(shí)現(xiàn)了IAnimal的接口,但“人”和“豬”的實(shí)現(xiàn)不一樣,為了避免太多代碼導(dǎo)致影響閱讀,這里的代碼簡化成一行,但輸出的內(nèi)容不一樣,實(shí)際項(xiàng)目中同一接口的同一功能點(diǎn),不同的類實(shí)現(xiàn)完全不一樣 * 2)這里同樣是“人”這個(gè)類,但和前面介紹類時(shí)給的類“Person”完全不一樣,這是因?yàn)橥瑯拥倪壿嫺拍?在不同的應(yīng)用場景下,具備的屬性和功能是完全不一樣的 */package com.oo.demo; public class Person2 implements IAnimal { public void eat(){System.out.println("Person like to eat meat");}public void run(){System.out.println("Person run: left leg, right leg");}public void sleep(){System.out.println("Person sleep 8 hours every dat"); }public void speak(){System.out.println("Hellow world, I am a person");} }=================第四部分:Tester03.java package com.oo.demo;public class Tester03 {public static void main(String[] args) {System.out.println("===This is a person==="); IAnimal person = new Person2();person.eat();person.run();person.sleep();person.speak();System.out.println("\n===This is a pig===");IAnimal pig = new Pig();pig.eat();pig.run();pig.sleep();pig.speak();} } java中的interface

PS:hi boy,給我開個(gè)查詢接口。。。此時(shí)的接口指的是:自己提供給使用者來調(diào)用自己功能的方式\方法\入口

2. 為何要用接口

接口提取了一群類共同的函數(shù),可以把接口當(dāng)做一個(gè)函數(shù)的集合。

然后讓子類去實(shí)現(xiàn)接口中的函數(shù)。

這么做的意義在于歸一化,什么叫歸一化,就是只要是基于同一個(gè)接口實(shí)現(xiàn)的類,那么所有的這些類產(chǎn)生的對(duì)象在使用時(shí),從用法上來說都一樣。

?

歸一化的好處在于:

1. 歸一化讓使用者無需關(guān)心對(duì)象的類是什么,只需要的知道這些對(duì)象都具備某些功能就可以了,這極大地降低了使用者的使用難度。

2. 歸一化使得高層的外部使用者可以不加區(qū)分的處理所有接口兼容的對(duì)象集合

2.1:就好象linux的泛文件概念一樣,所有東西都可以當(dāng)文件處理,不必關(guān)心它是內(nèi)存、磁盤、網(wǎng)絡(luò)還是屏幕(當(dāng)然,對(duì)底層設(shè)計(jì)者,當(dāng)然也可以區(qū)分出“字符設(shè)備”和“塊設(shè)備”,然后做出針對(duì)性的設(shè)計(jì):細(xì)致到什么程度,視需求而定)。

2.2:再比如:我們有一個(gè)汽車接口,里面定義了汽車所有的功能,然后由本田汽車的類,奧迪汽車的類,大眾汽車的類,他們都實(shí)現(xiàn)了汽車接口,這樣就好辦了,大家只需要學(xué)會(huì)了怎么開汽車,那么無論是本田,還是奧迪,還是大眾我們都會(huì)開了,開的時(shí)候根本無需關(guān)心我開的是哪一類車,操作手法(函數(shù)調(diào)用)都一樣

3. 模仿interface

在python中根本就沒有一個(gè)叫做interface的關(guān)鍵字,如果非要去模仿接口的概念

可以借助第三方模塊:

http://pypi.python.org/pypi/zope.interface

twisted的twisted\internet\interface.py里使用zope.interface

文檔https://zopeinterface.readthedocs.io/en/latest/

設(shè)計(jì)模式:https://github.com/faif/python-patterns

?

也可以使用繼承:?

繼承的兩種用途

一:繼承基類的方法,并且做出自己的改變或者擴(kuò)展(代碼重用):實(shí)踐中,繼承的這種用途意義并不很大,甚至常常是有害的。因?yàn)樗沟米宇惻c基類出現(xiàn)強(qiáng)耦合。

二:聲明某個(gè)子類兼容于某基類,定義一個(gè)接口類(模仿java的Interface),接口類中定義了一些接口名(就是函數(shù)名)且并未實(shí)現(xiàn)接口的功能,子類繼承接口類,并且實(shí)現(xiàn)接口中的功能

class Interface:#定義接口Interface類來模仿接口的概念,python中壓根就沒有interface關(guān)鍵字來定義一個(gè)接口。def read(self): #定接口函數(shù)readpassdef write(self): #定義接口函數(shù)writepassclass Txt(Interface): #文本,具體實(shí)現(xiàn)read和writedef read(self):print('文本數(shù)據(jù)的讀取方法')def write(self):print('文本數(shù)據(jù)的讀取方法')class Sata(Interface): #磁盤,具體實(shí)現(xiàn)read和writedef read(self):print('硬盤數(shù)據(jù)的讀取方法')def write(self):print('硬盤數(shù)據(jù)的讀取方法')class Process(Interface):def read(self):print('進(jìn)程數(shù)據(jù)的讀取方法')def write(self):print('進(jìn)程數(shù)據(jù)的讀取方法') View Code

上面的代碼只是看起來像接口,其實(shí)并沒有起到接口的作用,子類完全可以不用去實(shí)現(xiàn)接口?,這就用到了抽象類

七 抽象類

1 什么是抽象類

? ? 與java一樣,python也有抽象類的概念但是同樣需要借助模塊實(shí)現(xiàn),抽象類是一個(gè)特殊的類,它的特殊之處在于只能被繼承,不能被實(shí)例化

2 為什么要有抽象類

? ? 如果說類是從一堆對(duì)象中抽取相同的內(nèi)容而來的,那么抽象類是從一堆中抽取相同的內(nèi)容而來的,內(nèi)容包括數(shù)據(jù)屬性和函數(shù)屬性。

  比如我們有香蕉的類,有蘋果的類,有桃子的類,從這些類抽取相同的內(nèi)容就是水果這個(gè)抽象的類,你吃水果時(shí),要么是吃一個(gè)具體的香蕉,要么是吃一個(gè)具體的桃子。。。。。。你永遠(yuǎn)無法吃到一個(gè)叫做水果的東西。

? ? 從設(shè)計(jì)角度去看,如果類是從現(xiàn)實(shí)對(duì)象抽象而來的,那么抽象類就是基于類抽象而來的。

  從實(shí)現(xiàn)角度來看,抽象類與普通類的不同之處在于:抽象類中只能有抽象方法(沒有實(shí)現(xiàn)功能),該類不能被實(shí)例化,只能被繼承,且子類必須實(shí)現(xiàn)抽象方法。這一點(diǎn)與接口有點(diǎn)類似,但其實(shí)是不同的,即將揭曉答案

3. 在python中實(shí)現(xiàn)抽象類

#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' #一切皆文件 import abc #利用abc模塊實(shí)現(xiàn)抽象類class All_file(metaclass=abc.ABCMeta):all_type='file'@abc.abstractmethod #定義抽象方法,無需實(shí)現(xiàn)功能def read(self):'子類必須定義讀功能'pass@abc.abstractmethod #定義抽象方法,無需實(shí)現(xiàn)功能def write(self):'子類必須定義寫功能'pass# class Txt(All_file): # pass # # t1=Txt() #報(bào)錯(cuò),子類沒有定義抽象方法class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('文本數(shù)據(jù)的讀取方法')def write(self):print('文本數(shù)據(jù)的讀取方法')class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('硬盤數(shù)據(jù)的讀取方法')def write(self):print('硬盤數(shù)據(jù)的讀取方法')class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('進(jìn)程數(shù)據(jù)的讀取方法')def write(self):print('進(jìn)程數(shù)據(jù)的讀取方法')wenbenwenjian=Txt()yingpanwenjian=Sata()jinchengwenjian=Process()#這樣大家都是被歸一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read()print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type) View Code

4. 抽象類與接口

抽象類的本質(zhì)還是類,指的是一組類的相似性,包括數(shù)據(jù)屬性(如all_type)和函數(shù)屬性(如read、write),而接口只強(qiáng)調(diào)函數(shù)屬性的相似性。

抽象類是一個(gè)介于類和接口直接的一個(gè)概念,同時(shí)具備類和接口的部分特性,可以用來實(shí)現(xiàn)歸一化設(shè)計(jì)?

八?繼承實(shí)現(xiàn)的原理(可惡的菱形問題)

1 繼承順序

在Java和C#中子類只能繼承一個(gè)父類,而Python中子類可以同時(shí)繼承多個(gè)父類,如A(B,C,D)

如果繼承關(guān)系為非菱形結(jié)構(gòu),則會(huì)按照先找B這一條分支,然后再找C這一條分支,最后找D這一條分支的順序直到找到我們想要的屬性

如果繼承關(guān)系為菱形結(jié)構(gòu),那么屬性的查找方式有兩種,分別是:深度優(yōu)先和廣度優(yōu)先

class A(object):def test(self):print('from A')class B(A):def test(self):print('from B')class C(A):def test(self):print('from C')class D(B):def test(self):print('from D')class E(C):def test(self):print('from E')class F(D,E):# def test(self):# print('from F')pass f1=F() f1.test() print(F.__mro__) #只有新式才有這個(gè)屬性可以查看線性列表,經(jīng)典類沒有這個(gè)屬性#新式類繼承順序:F->D->B->E->C->A #經(jīng)典類繼承順序:F->D->B->A->E->C #python3中統(tǒng)一都是新式類 #pyhon2中才分新式類與經(jīng)典類 繼承順序 View Code

2 繼承原理(python如何實(shí)現(xiàn)的繼承)

python到底是如何實(shí)現(xiàn)繼承的,對(duì)于你定義的每一個(gè)類,python會(huì)計(jì)算出一個(gè)方法解析順序(MRO)列表,這個(gè)MRO列表就是一個(gè)簡單的所有基類的線性順序列表,例如

>>> F.mro() #等同于F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

?

為了實(shí)現(xiàn)繼承,python會(huì)在MRO列表上從左到右開始查找基類,直到找到第一個(gè)匹配這個(gè)屬性的類為止。
而這個(gè)MRO列表的構(gòu)造是通過一個(gè)C3線性化算法來實(shí)現(xiàn)的。我們不去深究這個(gè)算法的數(shù)學(xué)原理,它實(shí)際上就是合并所有父類的MRO列表并遵循如下三條準(zhǔn)則:
1.子類會(huì)先于父類被檢查
2.多個(gè)父類會(huì)根據(jù)它們?cè)诹斜碇械捻樞虮粰z查
3.如果對(duì)下一個(gè)類存在兩個(gè)合法的選擇,選擇第一個(gè)父類

九 子類中調(diào)用父類的方法

方法一:指名道姓,即父類名.父類方法()

#_*_coding:utf-8_*_ __author__ = 'Linhaifeng'class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動(dòng)啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):Vehicle.__init__(self,name,speed,load,power)self.line=linedef run(self):print('地鐵%s號(hào)線歡迎您' %self.line)Vehicle.run(self)line13=Subway('中國地鐵','180m/s','1000人/箱','',13) line13.run() View Code

方法二:super()

class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動(dòng)啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):#super(Subway,self) 就相當(dāng)于實(shí)例本身 在python3中super()等同于super(Subway,self)super().__init__(name,speed,load,power)self.line=linedef run(self):print('地鐵%s號(hào)線歡迎您' %self.line)super(Subway,self).run()class Mobike(Vehicle):#摩拜單車passline13=Subway('中國地鐵','180m/s','1000人/箱','',13) line13.run() View Code?

強(qiáng)調(diào):二者使用哪一種都可以,但最好不要混合使用?

?

了解部分:

即使沒有直接繼承關(guān)系,super仍然會(huì)按照mro繼續(xù)往后查找

#A沒有繼承B,但是A內(nèi)super會(huì)基于C.mro()繼續(xù)往后找 class A:def test(self):super().test() class B:def test(self):print('from B') class C(A,B):passc=C() c.test() #打印結(jié)果:from Bprint(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] View Code

指名道姓與super()的區(qū)別

#指名道姓 class A:def __init__(self):print('A的構(gòu)造方法') class B(A):def __init__(self):print('B的構(gòu)造方法')A.__init__(self)class C(A):def __init__(self):print('C的構(gòu)造方法')A.__init__(self)class D(B,C):def __init__(self):print('D的構(gòu)造方法')B.__init__(self)C.__init__(self)pass f1=D() #A.__init__被重復(fù)調(diào)用 ''' D的構(gòu)造方法 B的構(gòu)造方法 A的構(gòu)造方法 C的構(gòu)造方法 A的構(gòu)造方法 '''#使用super() class A:def __init__(self):print('A的構(gòu)造方法') class B(A):def __init__(self):print('B的構(gòu)造方法')super(B,self).__init__()class C(A):def __init__(self):print('C的構(gòu)造方法')super(C,self).__init__()class D(B,C):def __init__(self):print('D的構(gòu)造方法')super(D,self).__init__()f1=D() #super()會(huì)基于mro列表,往后找 ''' D的構(gòu)造方法 B的構(gòu)造方法 C的構(gòu)造方法 A的構(gòu)造方法 ''' View Code

當(dāng)你使用super()函數(shù)時(shí),Python會(huì)在MRO列表上繼續(xù)搜索下一個(gè)類。只要每個(gè)重定義的方法統(tǒng)一使用super()并只調(diào)用它一次,那么控制流最終會(huì)遍歷完整個(gè)MRO列表,每個(gè)方法也只會(huì)被調(diào)用一次(注意注意注意:使用super調(diào)用的所有屬性,都是從MRO列表當(dāng)前的位置往后找,千萬不要通過看代碼去找繼承關(guān)系,一定要看MRO列表

?

轉(zhuǎn)載于:https://www.cnblogs.com/zhanglin123/p/9268997.html

總結(jié)

以上是生活随笔為你收集整理的面向对象之继承与派生的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 亚洲精品国产精品乱码桃花 | 国产综合av | 国产成人久久精品流白浆 | 91丨九色丨丰满 | 欧美日韩精品电影 | 99夜色 | 91麻豆国产在线观看 | 国产特黄级aaaaa片免 | 成人7777 | 欧美中文字幕第一页 | 亚洲精品视频一区 | 假日游船 | 日韩欧美在线观看免费 | 人妻91麻豆一区二区三区 | 韩日av片 | 免费中文字幕在线观看 | a级黄色一级片 | 亚洲黄色小说网 | 麻豆网站在线 | 黄色大片免费网站 | 毛片黄片免费看 | 欧美一区二区三区激情视频 | 欧美日韩加勒比 | 中文字幕在线免费观看视频 | 黄色的网站免费看 | 色播五月激情五月 | 毛片网 | 成人激情社区 | 成人免费午夜视频 | 韩国一二三区 | 久久一区av | 99re6在线| 国产乱仑视频 | 亚洲乱码在线 | 欧美综合影院 | 图片区 小说区 区 亚洲五月 | 台湾色综合 | 久久精品aⅴ无码中文字字幕重口 | 国产乱码精品1区2区3区 | 高清视频一区 | 黄色片在哪看 | 国产白浆在线观看 | 俺啪也 | 啪啪啪毛片 | 亚洲天堂一二三 | 成年人黄色片网站 | 伊人网色 | 黄色日韩| www.com捏胸挤出奶 | jizz日本18 | 97超碰在线免费 | 91亚洲视频在线观看 | 91pron在线| 一区精品视频在线观看 | 热热热色 | 欧美一二三区视频 | 干极品美女 | 91视频导航| 国语播放老妇呻吟对白 | caopor在线视频| 老熟妇仑乱一区二区视频 | 天堂av中文在线 | 久久久精品一区 | 日韩精品影视 | 久久艹精品 | 国产最新视频在线 | 永久免费看黄 | 口爆吞精一区二区三区 | 四虎综合网 | 四虎永久免费影院 | 国产成年无码久久久久毛片 | 538国产精品一区二区免费视频 | 黄色视屏软件 | 国精无码欧精品亚洲一区蜜桃 | 高跟肉丝丝袜呻吟啪啪网站av | 亚洲小说在线 | 活大器粗np高h一女多夫 | 欧美做受高潮1 | 国产日韩精品视频 | 在线观看国产黄色 | 国产伦子伦对白视频 | 国产suv精品一区二区68 | 亚洲国产欧美日韩 | 国产一区欧美日韩 | 蜜桃av在线免费观看 | 懂色a v | 日本免费一区二区在线 | 欧美日韩在线播放 | 久久久成人精品一区二区三区 | 自拍偷拍p| 国产精品白浆一区二小说 | 国产亚洲色婷婷久久99精品91 | 国产理论片 | 午夜视频导航 | 日韩视频在线观看一区二区三区 | 人妻一区二区三 | 国产a√精品区二区三区四区 | 国产欧美在线观看 | 美国成人免费视频 |