寫在前面的話html
終於,又到了週五。當小夥伴們都再也不加班歡歡喜喜過週末的時候,我剛剛寫完這一週的遊戲做業,從面對晚歸的緊皺眉頭到如今的從容淡定,好像只有那麼幾周的時間。忽然發現:改變——原來這麼簡單。不少時候咱們在想要爲本身的青春拼搏一次的時候都輸給了偶爾的抵觸和輕鬆愉悅的生活。咱們不過和走到最後的人差了兩個字——堅持!因此儘管進入類和對象這一部分,你們都會有畏難心理,可是堅持一下下,你就會是那個走到最後的人!python
回顧 程序員
上一篇中咱們初步的認識了類和對象,告終了它們的一些語法,就至關於獲得了一個對象的骨骼。今天再來補充一些和他們相關的內容,給咱們的小骷髏添上肌肉和皮膚,它就是一個活生生的對象了,今後你也是一個有對象的人了!哈~ide
首先咱們從面向對象的特性這個角度先回顧一下上一篇的內容,以前咱們已經知道了「車」是一個類,車的「品牌」和「價格」是它的屬性,能夠在路上跑是他的行爲;所以咱們定義了一個類car,並在這個car類中定義了price和type兩個屬性,還有一個DriveDistance方法。咱們說,這個car類就像是一個收納包,把和「車」有關的零散屬性、方法都裝進了包裏,這就是面向對象的封裝性。ui
面向對象的三大特性spa
上一篇咱們講的主要內容都符合面向對象的封裝特性。那麼問題來了?面向對象難道只有封裝性麼?固然不是,做爲一個這麼難理解的東西,要是隻有封裝性都對不起咱們死了這麼多腦細胞!因此,晴天霹靂來了,面向對象有三大特性,他們分別是:封裝、繼承和多態。code
好消息和好消息和好消息,好消息一:封裝咱們已講完,因此三座大山咱們已經移走了一座,好消息二:因爲python的特殊性,多態的應用並不普遍,因此咱們其實還有一座半就勝利了,好消息三:前面那兩條好消息都是真的。閒話少敘,今天我們就聊聊繼承,移走一座是一座!htm
正題——面向對象的繼承性對象
1、繼承blog
大學同窗聚會,同桌吃飯,咱們都是人,都有吃飯、喝飲料這些行爲,可是畢業以後你們都作了不一樣的工做,有的當了會計、有的作了程序員,如今咱們獲得了描述這些同窗這個需求,咱們一看很是開心,咱們能夠實現呀,而後寫下了下面左圖的代碼:
咱們看上面左側的代碼,這麼寫確實實現了咱們的需求,可是,寫了那麼多行,真正不同的只有黃色框框裏面的內容,好在大學同窗的職業都差很少,這要是高中聚會可就熱鬧了。這個時候,咱們就想,有沒有可能咱們不重複寫以前的代碼,也實現一樣的功能呢?固然啦!→_→右側這段代碼。看着就簡潔了很多,這就是類的繼承。如今你看着好像有點兒迷糊,不要緊,這裏只須要知道有一種簡單的方法能夠實現,這種寫法就叫作繼承。具體咱們後面還要詳細講。
咱們來詳細看看上面這張圖,解釋一下什麼叫作繼承,首先在最上面的黃框框裏,咱們定義了一個類叫作classmate,這個裏面放了吃、喝兩個方法,下面咱們又定義了兩個類,pythoner和accounting類,裏面各寫了一個occupation方法,打印出了人物的職業。咱們看到,classmate類和咱們以前見到的類並沒什麼不一樣,但是pythoner和accounting類定義的時候,咱們看紅框框裏寫了classmate類的類名,咱們說,這樣就實現了繼承。pythoner和accounting類集成了classmate的全部屬性和方法。
說完了繼承類的定義,咱們再來看看實例化和調用,咱們看上面右側那張小圖,咱們分別實例化了兩個對象,eva和sweet,注意看紅框框裏咱們實例化的是pythoner和accounting這兩個派生類,可是咱們卻能夠調用classmate的eat和drink方法,並且咱們在occupation中也可使用父類的name屬性。magic!代碼在下面~
1 class classmate(): 2 def __init__(self,name): 3 self.name = name 4 def eat(self): 5 print '%s is eating.'%self.name 6 def drink(self): 7 print '%s is drinking'%self.name 8 9 10 class pythoner(classmate): 11 def occupation(self): 12 print '%s is a pythoner.'%self.name 13 14 class accounting(classmate): 15 def occupation(self): 16 print '%s is a accounting.'%self.name 17 18 eva = pythoner('eva') 19 eva.occupation() 20 eva.eat() 21 eva.drink() 22 23 sweet = accounting('sweet') 24 sweet.occupation() 25 sweet.eat() 26 sweet.drink()
2、多繼承
如今咱們基本可使用類的繼承描述同坐一桌的同窗們了,可是咱們如今又有了一個新需求,就是把這一桌的男生和女生分開,男生喝酒,女生喝飲料,這個需求怎麼用類來區別呢?先上圖~
咱們看上面左側這張圖,因爲需求的增長,要求把同桌的男生和女生分開,我又新寫了兩個female和male類從新定義drink方法,而且又定義了新的類fe_pythoner和ma_pythoner,因此這兩個類什麼也不作,只是分別繼承female、classmate和male、classmate類。在實例化對象的時候咱們使用fe_pythoner和ma_pythoner,咱們這樣猜測,這個時候對象eva和sweet是否是應該分別去調用female和male中的drink方法呢?執行下,看看下面的結果。什麼鬼?居然仍是輸出了基類的drink方法。再看看右邊,沒錯,我只是在定義基類的時候讓基類繼承了object,它就能夠按照咱們想要的方法輸出了。
3、經典類的深度優先和新式類的廣度優先
那麼原理是什麼呢?這個時候我就要盜一張圖來解釋這個問題了:
咱們看上面的圖,先放兩句概念上來嚇唬嚇唬你:
那麼什麼是經典類和新式類呢?簡而言之,繼承自object的類就叫作新式類,object類是python提供的,如今咱們還不須要管它從哪裏來,由於讓類中的不少操做變得更合理了,咱們之後記着就這麼寫就對了。注:下面小夥伴提到,python3.X版本中的類繼承默認就是廣度優先。
下面來講廣度優先和深度優先,首先,B和C兩個類都必須繼承自D,A類又繼承自B、C,就是針對這種狀況,沒有爲何。。。背下來!咱們對應起來看,這裏的基類D就是上例中的classmate,BC就是pythoner和female,A則對應fe_pythoner類。
經典類中:當咱們這樣寫:fe_pythoner(pythoner,female),對象調用方法的時候,會先在fe_pythoner裏面找,而後依次去找pythoner、classmate、最後再找female。若是找到了,就會執行,而且再也不繼續找下去了。因此咱們剛剛在左側舉出得栗子中它先找到了classmate中的drink方法,纔打印出了一樣的內容。這就是深度優先。
新式類中:當咱們這樣寫:fe_pythoner(pythoner,female),對象調用方法的時候,會先在fe_pythoner裏面找,而後依次去找pythoner、female、最後再找classmate。若是找到了,就會執行,而且再也不繼續找下去了。因此咱們剛剛在右側舉得栗子中它先找到了female、或male中的drink方法,就打印了不一樣的內容。這就是廣度優先。
1 class classmate(object): 2 def __init__(self,name): 3 self.name = name 4 5 def eat(self): 6 print '%s is eating.'%self.name 7 8 def drink(self): 9 print '%s is drinking'%self.name 10 11 class female(classmate): 12 13 def drink(self): 14 print '%s drink orange juice'%self.name 15 16 class male(classmate): 17 18 def drink(self): 19 print '%s drink alcohol'%self.name 20 21 class pythoner(classmate): 22 23 def occupation(self): 24 print '%s is a pythoner.'%self.name 25 26 27 28 class fe_pythoner(pythoner,female): 29 pass 30 class male_pythoner(pythoner,male): 31 pass 32 33 eva = fe_pythoner('eva') 34 eva.drink() 35 36 sweet = male_pythoner('sweet') 37 sweet.drink()
若是上面那些你統統沒搞清楚,也不要緊,在繼承的時候能夠直接把female類寫在前面 fe_pythoner(female,pythoner),這麼一來無論怎麼樣,都是先找female了。
好了,到如今爲止咱們如今已經移走了面向對象的第二座大山,離勝利又進了一步,感謝努力的本身,又多堅持了一下~~~