python--7、物件導向

來源:互聯網
上載者:User

標籤:nbsp   使用情境   大型   super   交通   合并   使用   網路   注意   

什麼是物件導向

對象,即抽象的一類事物中的某個具體的個體。這個世界中存在的一切皆為對象,不存在的也能建立出來。

較之面向過程的區別:
  • 編程的複雜度遠高於面向過程,不瞭解物件導向而立即上手基於它設計程式,極容易出現過度設計的問題。擴充性要求低的程式更適合用面向過程。
  • 無法向面向過程的程式設計流水線式的可以很精準的預測問題的處理流程與結果,物件導向的程式一旦開始就由對象之間的互動解決問題,無法準確地預測最終結果。
應用情境:

需求經常變化的軟體,一般需求的變化都是集中在使用者層的。

類與對象

類,即類別。對象是特徵與能力的結合體,而類則是一系列對象相似的特徵與技能的結合體。
在程式中,一定是先有類,再有對象。
定義類的依據:

類中的屬性
  • 資料屬性:只要是這個類產生的對象均會共用
  • 函數屬性:類中定義的函數,綁定給對象用的。被稱為方法。綁定到對象的方法的特殊之處為,綁定給誰就由誰調用,把調用者當做第一個參數傳進去,所以類中定義的函數都要預設寫一個參數self。
對象之間的互動
class A:    state = ‘china‘    def __init__(self,name,HP,strength)        self.name = name        self.HP = HP        self.strength = strength    def war(self,enemy):        ememy.HP -= self.strength        print(‘%s剩餘生命值%s‘%(ememy.name,ememy.HP))class B:    state = ‘USA‘    def __init__(self,name,HP,strength)        self.name = name        self.HP = HP        self.strength = strength    def war(self,enemy):        ememy.HP -= self.strength        print(‘%s剩餘生命值%s‘%(ememy.name,ememy.HP))soldier = A(‘soldier‘,100,9)criminal = B(‘criminal‘,100,5)soldier.war(criminal)
繼承

解決代碼的重用。建立的類可以繼承多個父類,這些父類稱為基類或超類。建立的類稱為衍生類別或子類。
只繼承一個類稱為單繼承。繼承多個類稱為多繼承。

查看繼承
  • 類.__base__ 只查看最左邊繼承的類
  • 類.__bases__ 查看所有繼承的類
經典類與新式類

1.只有在python2中才分新式類和經典類,python3中統一都是新式類
2.在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類
3.在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類
4.在python3中,無論是否繼承object,都預設繼承object,即python3中所有類均為新式類
註:若未指定基類,預設會繼承object類。object類是所有python類的基類,提供了一些通用方法。

繼承與抽象抽象

抽象即字面意思,抽取類似的或者比較像的部門。
抽象分為兩個層次:先把相似的對象抽取成一個類,在把多個類抽取出一個父類。

繼承

基於抽象出的結果,使用程式設計語言去實現它。必然要先抽象,再通過繼承的方式去表達出抽象的結構

繼承與重用性
#例如要分別建立一些貓和狗。可以分析出貓和狗都有的一些共性。如吃、喝、拉、撒。class Animal:    def eat(self):        pass    def drink(self):        pass    def shit(self):        pass    def pee(self):        passclass Cat(Animal):    def __init__(self, name):        self.name = name        self.breed = ‘貓‘    def cry(self):        print(‘喵~喵‘)class Dog(Animal):    def __init__(self, name):        self.name = name        self.breed=‘狗‘    def cry(self):        print(‘汪~汪‘)c = Cat(‘小白的小白貓‘)c.drink()d1 = Dog(‘胖子家的小瘦狗‘)d1.eat()

#註:執行個體尋找屬性和方法時,先從執行個體中找,再去父類找,直到最頂級的父類。
#提示:用已經有的類建立一個新的類,這樣就重用了已經有的軟體中的一部分設定大部分,大大生了編程工作量,這就是常說的軟體重用,不僅可以重用自己的類,也可以繼承別人的,比如標準庫,來定製新的資料類型,這樣就是大大縮短了軟體開發週期,對大型軟體開發來說,意義重大.

派生

當然子類也可以添加自己新的屬性或者在自己這裡重新定義這些屬性(不會影響到父類),需要注意的是,一旦重新定義了自己的屬性且與父類重名,那麼調用新增的屬性時,就以自己為準了。
在子類中,建立的重名的函數屬性,在編輯函數內功能的時候,有可能需要重用父類中重名的那個函數功能,應該是用調用普通函數的方式,即:類名.func(),此時就與調用普通函數無異了,因此即便是self參數也要為其傳值。在py3中,推薦用super()調用父類的屬性和方法。

組合與重用性

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

組合指的是,在一個類中以另外一個類的對象作為資料屬性,稱為類的組合
把一個類的實力屬性賦值為別的執行個體或者別的類。
組合與繼承都是有效地利用已有類的資源的重要方式。但是二者的概念和使用情境皆不同,
1.繼承的方式
通過繼承建立了衍生類別與基類之間的關係,它是一種‘是‘的關係,比如白馬是馬,人是動物。
當類之間有很多相同的功能,提取這些共同的功能做成基類,用繼承比較好,比如老師是人,學生是人

2.組合的方式
用組合的方式建立了類與組合的類之間的關係,它是一種‘有’的關係,比如教授有生日,教授教python和linux課程,教授有學生s1、s2、s3...

當類之間有顯著不同,並且較小的類是較大的類所需要的組件時,用組合比較好

介面與歸一化設計Java中的介面
  • Java的Interface介面的特徵:
  • 1)是一組功能的集合,而不是一個功能
  • 2)介面的功能用於互動,所有的功能都是public,即別的對象可操作
  • 3)介面只定義函數,但不涉及函數實現
  • 4)這些功能是相關的,都是動物相關的功能,但光合作用就不適宜放到IAnimal裡面了 */
為何要用介面

介面提取了一群類共同的函數,可以把介面當做一個函數的集合。

然後讓子類去實現介面中的函數。

這麼做的意義在于歸一化,什麼叫歸一化,就是只要是基於同一個介面實現的類,那麼所有的這些類產生的對象在使用時,從用法上來說都一樣。

歸一化的好處在於:

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

  2. 歸一化使得高層的外部使用者可以不加區分的處理所有介面相容的對象集合

2.1:就好象linux的泛檔案概念一樣,所有東西都可以當檔案處理,不必關心它是記憶體、磁碟、網路還是螢幕(當然,對底層設計者,當然也可以區分出“字元裝置”和“塊裝置”,然後做出針對性的設計:細緻到什麼程度,視需求而定)。

繼承的兩種用途

一:繼承基類的方法,並且做出自己的改變或者擴充(代碼重用):實踐中,繼承的這種用途意義並不很大,甚至常常是有害的。因為它使得子類與基類出現強耦合。

二:聲明某個子類相容於某基類,定義一個介面類(模仿java的Interface),介面類中定義了一些介面名(就是函數名)且並未實現介面的功能,子類繼承介面類,並且實現介面中的功能

繼承實現的原理1.繼承順序

2.繼承原理(python如何?的繼承)

python到底是如何?繼承的,對於你定義的每一個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的所有基類的線性順序列表,例如

F.mro() #等同於F.mro [<class ‘main.F‘>, <class ‘main.D‘>, <class ‘main.B‘>, <class ‘main.E‘>, <class ‘main.C‘>, <class ‘main.A‘>, <class ‘object‘>]

為了實現繼承,python會在MRO列表上從左至右開始尋找基類,直到找到第一個匹配這個屬性的類為止。 而這個MRO列表的構造是通過一個C3線性化演算法來實現的。我們不去深究這個演算法的數學原理,它實際上就是合并所有父類的MRO列表並遵循如下三條準則: 1.子類會先於父類被檢查 2.多個父類會根據它們在列表中的順序被檢查 3.如果對下一個類存在兩個合法的選擇,選擇第一個父類

子類中調用父類的方法
class Vehicle: #定義交通工具類     Country=‘China‘     def __init__(self,name,speed,load,power):         self.name=name         self.speed=speed         self.load=load         self.power=power     def run(self):         print(‘開動啦...‘)class Subway(Vehicle): #地鐵    def __init__(self,name,speed,load,power,line):        #super(Subway,self) 就相當於執行個體本身 在python3中super()等同於super(Subway,self)        super().__init__(name,speed,load,power)        self.line=line    def run(self):        print(‘地鐵%s號線歡迎您‘ %self.line)        super(Subway,self).run()class Mobike(Vehicle):#摩拜單車    passline13=Subway(‘中國地鐵‘,‘180m/s‘,‘1000人/箱‘,‘電‘,13)line13.run()
super()與直接用父類名調用的區別

當你使用super()函數時,Python會在MRO列表上繼續搜尋下一個類。只要每個重定義的方法統一使用super()並只調用它一次,那麼控制流程最終會遍曆完整個MRO列表,每個方法也只會被調用一次(注意注意注意:使用super調用的所有屬性,都是從MRO列表當前的位置往後找,千萬不要通過看代碼去找繼承關係,一定要看MRO列表)

python--7、物件導向

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.