溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

等等!Python和鴨子它倆有什么關(guān)系?

發(fā)布時間:2020-08-09 18:00:36 來源:ITPUB博客 閱讀:129 作者:千鋒Python唐小強(qiáng) 欄目:編程語言

眾所周知,Python作為膠水語言,它可以做的東西很多,爬蟲、人工智能、自動化測試、數(shù)據(jù)分析等等。而鴨子是一種動物,它可以做的東西也很多,啤酒鴨、香烤鴨、鹽水鴨、土豆?fàn)F鴨等等。按理說這兩個對應(yīng)著不同人體器官的東西應(yīng)該是扯不上關(guān)系的。

等等!Python和鴨子它倆有什么關(guān)系?

但是,偏偏就有辣莫一個人,美國詩人詹姆斯·惠特科姆·萊利,在17世紀(jì)時寫下了一句詩:

「When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.」

就是這短短的一句詩,讓這兩者扯上了神奇的關(guān)系,關(guān)鍵人們還為這種關(guān)系取了個名字 -- 鴨子類型。從此Python和鴨子就成就了一段佳話啊呸,那這 鴨子類型究竟是怎么回事呢?且往下看~

等等!Python和鴨子它倆有什么關(guān)系?

思考一個場景

加入在你擁有一款內(nèi)容聚合應(yīng)用,這款應(yīng)用每天會從各個門戶網(wǎng)站采集一些文章回來,并且分發(fā)至應(yīng)用里面的各個頻道。

這個時候我們可以將分發(fā)文章這個功能簡單的抽象為一個distribute函數(shù),該函數(shù)由兩個參數(shù)構(gòu)成,待分發(fā)文章article,分發(fā)頻道channel。

同時為了保證文章更符合頻道的內(nèi)容范圍和調(diào)性,在每篇文章分發(fā)至頻道時,最好都對文章做一些準(zhǔn)入校驗,于是我們初步封裝出以下函數(shù):

def distribute(article, channel):    # 文章準(zhǔn)入判斷    # 政務(wù)頻道的文章標(biāo)題不能出現(xiàn)‘震驚’字眼    if channel.name == 'politics' and article.title.find('震驚') >= 0:        return False    # 娛樂頻道不允許a,b這兩個作者的文章    elif channel.name == 'entertainment' and article.author in ['a','b']:        return False    # some elif here...    # 將文章與頻道的綁定關(guān)系寫進(jìn)數(shù)據(jù)庫    return bind_relation(article, channel)

上面的函數(shù)確實能夠?qū)崿F(xiàn)我們想要的功能了,但是存在一個顯而易見的問題:如果我們每增加一條準(zhǔn)入規(guī)則,就需要改動一次distribute函數(shù),這樣頻繁地對一個函數(shù)動刀顯然不是一個好的做法。

我們希望這個函數(shù)是一個更抽象的公共函數(shù),他不需要被過多的改動,于是我們做一點改進(jìn),變成下面的函數(shù):

def distribute(article, channel):    # 文章準(zhǔn)入判斷    can_push = channel.check(article)    # 將文章與頻道的綁定關(guān)系寫進(jìn)數(shù)據(jù)庫    if can_push:        return bind_relation(article, channel)    return False

將校驗頻道準(zhǔn)入規(guī)則的這個功能用頻道類自己實現(xiàn)的check方法封裝起來,這樣每當(dāng)有一個新的頻道需要創(chuàng)建,或者舊頻道需要更改校驗規(guī)則,則只需要負(fù)責(zé)維護(hù)各自頻道類的check方法就好了。

而distribute函數(shù)作為一個更高層級的存在則不會被影響到。

class Article:    def __init__(self, title, author):        self.title = title        self.author = authorclass EntertainmentChannel:    def __init__(self)        self.name = 'entertainment'    def check(article):        if article.author in ['a','b']:            return False        return Trueclass PoliticsChannel:    def __init__(self)        self.name = 'politics'    def check(article):        if article.title.find('震驚') >= 0:            return False        return Truearitcle_a = Article('震驚!大笑1小時壽命減少60分鐘!', 'a')aritcle_b = Article('戰(zhàn)勝恐懼最好的辦法?', 'b')politics_channel = PoliticsChannel()entertainment_channel = EntertainmentChannel()distribute(aritcle_a, politics_channel)  # Fasledistribute(aritcle_b, entertainment_channel)  # Fasle

多態(tài)

上面對于distribute函數(shù)的改造結(jié)果,其實很類似于面向?qū)ο笕筇卣髦?——  多態(tài)的應(yīng)用。

簡單解釋起來, 多態(tài)就是同一操作(方法)被作用于不同的對象時,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。

例如上面的check方法,當(dāng)它由EntertainmentChannel類實例調(diào)用時,檢查的是文章標(biāo)題不能包含“震驚”字眼;由PoliticsChannel類實例調(diào)用時,檢查的是文章作者不能是’a'和‘b’。

多態(tài)在靜態(tài)語言如 Java 中,通常通過子類繼承父類,然后子類重寫父類中的某些方法來實現(xiàn) 多態(tài)。但是在python中,不需要搞子承父業(yè)這一套,只需要在不同的類里面實現(xiàn)好名字相同的方法,即可在運行時表現(xiàn)出 多態(tài)。

只不過,這種特征在python中一般不叫 多態(tài),而是我們前面提到的—— 鴨子類型

鴨子類型

鴨子類型的名字來源和具體應(yīng)用場景前面已經(jīng)描述過了,而關(guān)于鴨子類型的定義,網(wǎng)上出現(xiàn)最多的就是對文章開頭那句英文詩句的翻譯:

如果一只鳥走起來像鴨子,發(fā)出的聲音像鴨子,游起來像鴨子,那么它就是一只鴨子

這句話重點在于引導(dǎo)我們只關(guān)注事物的行為,而不是關(guān)注事物本身和它的表現(xiàn)。再看一個幫助理解的栗子:

class Duck:    def sound(self):        print('quack')    def walk(self):        print('da da da')class Dog:    def sound(self):            print('wang')    def walk(self):        print('tita tita tita')def walk_and_sound(animal):    animal.walk()    animal.sound()dog = Dog()duck = Duck()walk_and_sound(dog) # tita tita tita wangwalk_and_sound(duck) # da da da quack

就好像一只狗會走,會叫;鴨子也會走,會叫。狗有很多行為都跟鴨子相似,他們做的動作是一樣的,只是表現(xiàn)出來不一樣。

我們關(guān)注的是類有什么方法,能做什么,而不是類是怎么定義的,表現(xiàn)出來是怎么樣的。這個正是 鴨子類型想表達(dá)的思想。

等等!Python和鴨子它倆有什么關(guān)系?

鴨子類型的思想

總結(jié)

  • 鴨子類型是python中多態(tài)的一種實現(xiàn)方式。
  • 鴨子類型強(qiáng)調(diào)關(guān)注事物的行為而不是事物本身和事物的表現(xiàn),如果某些類都實現(xiàn)了同名方法,那這些類就符合 鴨子類型

后記&引用

其實我仔細(xì)想了想,如果我早出生幾個世紀(jì),在詹姆斯·惠特科姆·萊利寫出那句詩之前,喊出 「如果一個四肢動物走起來像狗,叫起來像狗,傻起來像狗,那它就是一只狗」~這樣一句話。

是不是現(xiàn)在就不叫 鴨子類型而改叫 狗子類型呢?唉,又錯過了名留千史的機(jī)會,還是應(yīng)了一句老話:出名要趁早?。?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI