溫馨提示×

溫馨提示×

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

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

等等!Python和鴨子它倆有什么關系?

發布時間:2020-08-09 18:00:36 來源:ITPUB博客 閱讀:156 作者:千鋒Python唐小強 欄目:編程語言

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

等等!Python和鴨子它倆有什么關系?

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

「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.」

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

等等!Python和鴨子它倆有什么關系?

思考一個場景

加入在你擁有一款內容聚合應用,這款應用每天會從各個門戶網站采集一些文章回來,并且分發至應用里面的各個頻道。

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

同時為了保證文章更符合頻道的內容范圍和調性,在每篇文章分發至頻道時,最好都對文章做一些準入校驗,于是我們初步封裝出以下函數:

def distribute(article, channel):    # 文章準入判斷    # 政務頻道的文章標題不能出現‘震驚’字眼    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...    # 將文章與頻道的綁定關系寫進數據庫    return bind_relation(article, channel)

上面的函數確實能夠實現我們想要的功能了,但是存在一個顯而易見的問題:如果我們每增加一條準入規則,就需要改動一次distribute函數,這樣頻繁地對一個函數動刀顯然不是一個好的做法。

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

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

將校驗頻道準入規則的這個功能用頻道類自己實現的check方法封裝起來,這樣每當有一個新的頻道需要創建,或者舊頻道需要更改校驗規則,則只需要負責維護各自頻道類的check方法就好了。

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

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('戰勝恐懼最好的辦法?', 'b')politics_channel = PoliticsChannel()entertainment_channel = EntertainmentChannel()distribute(aritcle_a, politics_channel)  # Fasledistribute(aritcle_b, entertainment_channel)  # Fasle

多態

上面對于distribute函數的改造結果,其實很類似于面向對象三大特征之一 ——  多態的應用。

簡單解釋起來, 多態就是同一操作(方法)被作用于不同的對象時,可以有不同的解釋,產生不同的執行結果。

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

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

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

鴨子類型

鴨子類型的名字來源和具體應用場景前面已經描述過了,而關于鴨子類型的定義,網上出現最多的就是對文章開頭那句英文詩句的翻譯:

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

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

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

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

我們關注的是類有什么方法,能做什么,而不是類是怎么定義的,表現出來是怎么樣的。這個正是 鴨子類型想表達的思想。

等等!Python和鴨子它倆有什么關系?

鴨子類型的思想

總結

  • 鴨子類型是python中多態的一種實現方式。
  • 鴨子類型強調關注事物的行為而不是事物本身和事物的表現,如果某些類都實現了同名方法,那這些類就符合 鴨子類型。

后記&引用

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

是不是現在就不叫 鴨子類型而改叫 狗子類型呢?唉,又錯過了名留千史的機會,還是應了一句老話:出名要趁早??!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女