學(xué)Python最簡(jiǎn)單的方法是什么?
作為一名程序員或者準(zhǔn)程序員,對(duì)于面向?qū)ο?a target="_blank">編程簡(jiǎn)直熟悉的不能再熟悉。作為當(dāng)今最流行的編程思想之一(或許可以去掉“之一”),無(wú)論是在面試還是工作中,面向?qū)ο蠖际菬o(wú)法避開(kāi)的話題。
對(duì)于Python程序員來(lái)說(shuō),OOP(面向?qū)ο缶幊蹋┑娜筇匦浴獢?shù)據(jù)封裝、繼承和多態(tài)通常是面試中的重點(diǎn)考察問(wèn)題,因此大部分人對(duì)此也相當(dāng)熟悉。
不過(guò),OOP的優(yōu)缺點(diǎn)你真的了解嗎?今天這篇文章會(huì)帶領(lǐng)大家了解一下三大特點(diǎn)中繼承的優(yōu)缺點(diǎn)。
類(lèi)
OOP()即所謂面向?qū)ο缶幊?,是一種程序設(shè)計(jì)思想。OOP把對(duì)象作為程序的基本單元,一個(gè)對(duì)象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)。面向?qū)ο蟮某绦蛟O(shè)計(jì)把計(jì)算機(jī)程序視為一組對(duì)象的集合,而每個(gè)對(duì)象都可以接收其他對(duì)象發(fā)過(guò)來(lái)的消息,并處理這些消息,計(jì)算機(jī)程序的執(zhí)行就是一系列消息在各個(gè)對(duì)象之間傳遞。
面向?qū)ο笞钪匾母拍罹褪穷?lèi)(Class)和實(shí)例(Instance),必須牢記類(lèi)是抽象的模板,而實(shí)例是根據(jù)類(lèi)創(chuàng)建出來(lái)的一個(gè)個(gè)具體的“對(duì)象”,每個(gè)對(duì)象都擁有相同的方法,但各自的數(shù)據(jù)可能不同。
假設(shè)我們要?jiǎng)?chuàng)建一個(gè)Student類(lèi),在Python中,定義類(lèi)是通過(guò)class關(guān)鍵字:
class后面緊接著是類(lèi)名,即Student,類(lèi)名通常是大寫(xiě)開(kāi)頭的單詞,緊接著是(object),表示該類(lèi)是從哪個(gè)類(lèi)繼承下來(lái)的,繼承的概念我們后面再講,通常,如果沒(méi)有合適的繼承類(lèi),就使用object類(lèi),這是所有類(lèi)最終都會(huì)繼承的類(lèi)。
定義好了Student類(lèi),就可以根據(jù)Student類(lèi)創(chuàng)建出Student的實(shí)例,創(chuàng)建實(shí)例是通過(guò)類(lèi)名+()實(shí)現(xiàn)的:

可以看到,變量bart指向的就是一個(gè)Student的實(shí)例,后面的0x10a67a590是內(nèi)存地址,每個(gè)object的地址都不一樣,而Student本身則是一個(gè)類(lèi)。
可以自由地給一個(gè)實(shí)例變量綁定屬性,比如,給實(shí)例bart綁定一個(gè)name屬性:

由于類(lèi)可以起到模板的作用,因此,可以在創(chuàng)建實(shí)例的時(shí)候,把一些我們認(rèn)為必須綁定的屬性強(qiáng)制填寫(xiě)進(jìn)去。通過(guò)定義一個(gè)特殊的__init__方法,在創(chuàng)建實(shí)例的時(shí)候,就把name,score等屬性綁上去:

注意:特殊方法“__init__”前后分別有兩個(gè)下劃線?。?!
注意到__init__方法的第一個(gè)參數(shù)永遠(yuǎn)是self,表示創(chuàng)建的實(shí)例本身,因此,在__init__方法內(nèi)部,就可以把各種屬性綁定到self,因?yàn)閟elf就指向創(chuàng)建的實(shí)例本身。
有了__init__方法,在創(chuàng)建實(shí)例的時(shí)候,就不能傳入空的參數(shù)了,必須傳入與__init__方法匹配的參數(shù),但self不需要傳,Python解釋器自己會(huì)把實(shí)例變量傳進(jìn)去:

和普通的函數(shù)相比,在類(lèi)中定義的函數(shù)只有一點(diǎn)不同,就是第一個(gè)參數(shù)永遠(yuǎn)是實(shí)例變量self,并且,調(diào)用時(shí),不用傳遞該參數(shù)。除此之外,類(lèi)的方法和普通函數(shù)沒(méi)有什么區(qū)別,所以,你仍然可以用默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù)。
繼承
什么是繼承?
繼承是一種創(chuàng)建類(lèi)的方法,在python中,一個(gè)類(lèi)可以繼承來(lái)自一個(gè)或多個(gè)父類(lèi)。原始類(lèi)稱為基類(lèi)或超類(lèi)。

查看繼承:

什么時(shí)候用繼承?
假如已經(jīng)有幾個(gè)類(lèi),而類(lèi)與類(lèi)之間有共同的變量屬性和函數(shù)屬性,那就可以把這幾個(gè)變量屬性和函數(shù)屬性提取出來(lái)作為基類(lèi)的屬性。而特殊的變量屬性和函數(shù)屬性,則在本類(lèi)中定義,這樣只需要繼承這個(gè)基類(lèi),就可以訪問(wèn)基類(lèi)的變量屬性和函數(shù)屬性??梢蕴岣叽a的可擴(kuò)展性。
繼承和抽象(先抽象再繼承)
抽象即提取類(lèi)似的部分?;?lèi)就是抽象多個(gè)類(lèi)共同的屬性得到的一個(gè)類(lèi)。

Garen類(lèi)和Riven類(lèi)都有nickname、aggressivity、life_value、script四個(gè)變量屬性和attack()函數(shù)屬性,這里可以抽象出一個(gè)Hero類(lèi),里面有里面包含這些屬性。

嚴(yán)格來(lái)說(shuō),上述Hero.init(self,…),不能算作子類(lèi)調(diào)用父類(lèi)的方法。因?yàn)槲覀內(nèi)绻サ簦℉ero)這個(gè)繼承關(guān)系,代碼仍能得到預(yù)期的結(jié)果。
總結(jié)python中繼承的特點(diǎn):
在子類(lèi)中,并不會(huì)自動(dòng)調(diào)用基類(lèi)的init(),需要在派生類(lèi)中手動(dòng)調(diào)用。
在調(diào)用基類(lèi)的方法時(shí),需要加上基類(lèi)的類(lèi)名前綴,且需要帶上self參數(shù)變量。
先在本類(lèi)中查找調(diào)用的方法,找不到才去基類(lèi)中找。
繼承的優(yōu)缺點(diǎn)探討
子類(lèi)化內(nèi)置類(lèi)型的缺點(diǎn)
1. 內(nèi)置類(lèi)型的方法不會(huì)調(diào)用子類(lèi)覆蓋的方法
內(nèi)置類(lèi)可以子類(lèi)化,但是內(nèi)置類(lèi)型的方法不會(huì)調(diào)用子類(lèi)覆蓋的方法。下面以繼承dict的自定義子類(lèi)重寫(xiě)__setitem__為例說(shuō)明:

從輸出可以看到,鍵值對(duì)one=1和three=3存入a時(shí)均調(diào)用了dict的__setitem__,只有[]運(yùn)算符會(huì)調(diào)用我們預(yù)先覆蓋的方法。
問(wèn)題的解決方式在于不去子類(lèi)化dict,而是子類(lèi)化colections.UserDict。
2、子類(lèi)化collections中的類(lèi)
用戶自定義的類(lèi)應(yīng)該繼承collections模塊,如UserDict,UserList,UserString。這些類(lèi)做了特殊設(shè)計(jì),因此易于拓展。子類(lèi)化UserDict的代碼如下:

小結(jié):上述問(wèn)題只發(fā)生在C語(yǔ)言實(shí)現(xiàn)的內(nèi)置類(lèi)型子類(lèi)化情況中,而且只影響直接繼承內(nèi)置類(lèi)型的自定義類(lèi)。相反,子類(lèi)化使用Python編寫(xiě)的類(lèi),如UserDict或MutableMapping就不會(huì)有此問(wèn)題。
多重繼承
1. 方法解析順序(Method Resolution Order,MRO)
在多重繼承中存在不相關(guān)的祖先類(lèi)實(shí)現(xiàn)同名方法引起的沖突問(wèn)題,這種問(wèn)題稱作“菱形問(wèn)題”。Python依靠特定的順序遍歷繼承圖,這個(gè)順序叫做方法解析順序。如圖,左圖是類(lèi)的UML圖,右圖中的虛線箭頭是方法解析順序:

2、super
提到類(lèi)的屬性__mro__,就會(huì)提到super:
super 是個(gè)類(lèi),既不是關(guān)鍵字也不是函數(shù)等其他數(shù)據(jù)結(jié)構(gòu)。
作用:super是子類(lèi)用來(lái)調(diào)用父類(lèi)方法的。
語(yǔ)法:super(a_type, obj);
a_type是obj的__mro__,當(dāng)然也可以是__mro__的一部分,同時(shí)issubclass(obj,a_type)==true
舉個(gè)例子, 有個(gè) MRO: [A, B, C, D, E, object]
我們這樣調(diào)用:super(C, A).foo()
super 只會(huì)從 C 之后查找,即: 只會(huì)在 D 或 E 或 object 中查找 foo 方法。
下面構(gòu)造一個(gè)菱形問(wèn)題的多重繼承來(lái)深化理解:

輸出如下:

分析:d.pingpong()執(zhí)行super.ping(),super按照MRO查找父類(lèi)的ping方法,查詢?cè)陬?lèi)B到ping之后輸出了B.ping()。
3. 處理多重繼承的建議
(1)把接口繼承和實(shí)現(xiàn)繼承區(qū)分開(kāi);
繼承接口:創(chuàng)建子類(lèi)型,是框架的支柱;
繼承實(shí)現(xiàn):通過(guò)重用避免代碼重復(fù),通常可以換用組合和委托模式。
(2)使用抽象基類(lèi)顯式表示接口;
(3)通過(guò)混入重用代碼;混入類(lèi)為多個(gè)不相關(guān)的子類(lèi)提供方法實(shí)現(xiàn),便于重用,但不會(huì)實(shí)例化。并且具體類(lèi)不能只繼承混入類(lèi)。
(4)在名稱中明確指明混入;Python中沒(méi)有把類(lèi)聲明為混入的正規(guī)方式,Luciano推薦在名稱中加入Mixin后綴。如Tkinter中的XView應(yīng)變成XViewMixin。
(5)抽象基類(lèi)可以作為混入,反過(guò)來(lái)則不成立;抽象基類(lèi)與混入的異同:
抽象基類(lèi)會(huì)定義類(lèi)型,混入做不到;
抽象基類(lèi)可以作為其他類(lèi)的唯一基類(lèi),混入做不到;
抽象基類(lèi)實(shí)現(xiàn)的具體方法只能與抽象基類(lèi)及其超類(lèi)中的方法協(xié)作,混入沒(méi)有這個(gè)局限。
(6)不要子類(lèi)化多個(gè)具體類(lèi);具體類(lèi)可以沒(méi)有,或者至多一個(gè)具體超類(lèi)。例如,Class Dish(China,Japan,Tofu)中,如果Tofu是具體類(lèi),那么China和Japan必須是抽象基類(lèi)或混入。
(7)為用戶提供聚合類(lèi);聚合類(lèi)是指一個(gè)類(lèi)的結(jié)構(gòu)主要繼承自混入,自身沒(méi)有添加結(jié)構(gòu)或行為。Tkinter采納了此條建議。
(8)優(yōu)先使用對(duì)象組合,而不是類(lèi)繼承。優(yōu)先使用組合可以令設(shè)計(jì)更靈活。組合和委托可以代替混入,但不能取代接口繼承去定義類(lèi)型層次結(jié)構(gòu)。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7349瀏覽量
95054 -
python
+關(guān)注
關(guān)注
58文章
4889瀏覽量
90328 -
OOP
+關(guān)注
關(guān)注
0文章
14瀏覽量
9045
原文標(biāo)題:Python 繼承概念的這些優(yōu)缺點(diǎn)你知道嗎?
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
開(kāi)關(guān)電源拓?fù)浣Y(jié)構(gòu)特點(diǎn)和優(yōu)缺點(diǎn)對(duì)比
常見(jiàn)開(kāi)關(guān)電源拓?fù)浣Y(jié)構(gòu)的特點(diǎn)和優(yōu)缺點(diǎn)對(duì)比
天線各種材質(zhì)的優(yōu)缺點(diǎn)
步進(jìn)電機(jī)拆解/特點(diǎn)/優(yōu)缺點(diǎn)
多核系統(tǒng)的特點(diǎn)和優(yōu)缺點(diǎn)是什么
熱電偶測(cè)溫原理是什么?有哪些優(yōu)缺點(diǎn)?
什么是步進(jìn)電機(jī)?步進(jìn)電機(jī)有哪些優(yōu)缺點(diǎn)?
LwIP的優(yōu)缺點(diǎn)是什么
中央空調(diào)與分體空調(diào)的特點(diǎn)及優(yōu)缺點(diǎn)
OOP中繼承機(jī)制剖析
一文了解串行通信的特點(diǎn)及優(yōu)缺點(diǎn)
一文讀懂can總線的特點(diǎn)和優(yōu)缺點(diǎn)
了解OOP三大特點(diǎn)中繼承的優(yōu)缺點(diǎn)
評(píng)論