您好,登錄后才能下訂單哦!
這篇文章主要介紹使用Python實現(xiàn)多態(tài)、協(xié)議和鴨子類型的代碼,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
問起面向?qū)ο蟮娜筇匦?,幾乎每個人都能對答如流:封裝、繼承、多態(tài)。今天我們就要來說一說 Python 中的多態(tài)。
所謂多態(tài):就是指一個類實例的相同方法在不同情形有不同表現(xiàn)形式。多態(tài)機制使具有不同內(nèi)部結(jié)構(gòu)的對象可以共享相同的外部接口。這意味著,雖然針對不同對象的具體操作不同,但通過一個公共的類,它們(那些操作)可以通過相同的方式予以調(diào)用。
我在《Python 中的設(shè)計模式詳解之:策略模式》一文中詳細描述了策略模式的實現(xiàn),而策略模式就是典型的多態(tài)應(yīng)用。
之前的代碼我就不貼了,大家可以去原文中查看。我依然還是以商品折扣的經(jīng)典舉例。策略模式一文中,傳統(tǒng)的策略模式實現(xiàn)方式我也是用 Python 代碼實現(xiàn)的,在 java 或 C# 等語言中,實現(xiàn)方式也差不多。以下是 C# 代碼,我只列了個架子:
interface Promotion { double discount(Order order); } class FidelityPromo : Promotion // 第一個具體策略 { // 為積分為1000或以上的顧客提供5%折扣 public double discount(Order order) { ... } } class BulkItemPromo : Promotion // 第二個具體策略 { //單個商品為20個或以上時提供10%折扣 public double discount(Order order) { ... } } class LargeOrderPromo : Promotion // 第三個具體策略 { //訂單中的不同商品達到10個或以上時提供7%折扣 public double discount(Order order) { ... } }
可以看到,首先要有一個接口(Promotion),然后各個策略去實現(xiàn)這個接口。然而,Python 語言沒有 interface 關(guān)鍵字,就是說,Python 里沒有像 java、C# 一樣的接口。
在策略模式一文的實現(xiàn)中,使用了抽象基類(Abstract Base Class,ABC)來實現(xiàn)接口,這主要是為了寫法上看起來和 java、C# 等語言更加的像,易于有這些語言基礎(chǔ)的同學(xué)理解和對比。
抽象基類是在 Python 語言誕生 15 年后,Python 2.6 才引入的。這里我們不詳細介紹抽象基類,因為即便現(xiàn)在也很少有代碼使用抽象基類。對于多態(tài),Python 有更好的實現(xiàn)方式——鴨子類型(duck typing)。
所謂 鴨子類型 就是:如果一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么它就是鴨子。這個概念的名字來源于 James Whitcomb Riley 提出的鴨子測試。
初次看到這個描述的小伙伴一定一頭霧水,為了理解鴨子類型,我們不得不提到另一個名詞——協(xié)議。
在面向?qū)ο缶幊讨校瑓f(xié)議是非正式的接口,是一組方法,只由文檔和約定定義,因此,協(xié)議不能像正式接口那樣施加強制性約束。而 Python 的哲學(xué)就是盡量支持基本協(xié)議。
翻譯成人話,就是:Python 中沒有接口,在需要使用接口的地方,就用協(xié)議代替。所謂協(xié)議,其實就是一組方法,和接口中定義的方法一個意思。只不過協(xié)議是不是強制性的約定,如果你不遵守協(xié)議,那么也沒關(guān)系,運行時報錯就是了。
這樣就好理解鴨子類型了,“如果一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子” 這就表示已經(jīng)遵守了協(xié)議,“那么它就是鴨子”,意味著你可以在其他用到“鴨子”的地方,用“這只鳥”替換。這不就是多態(tài)嗎?
用“鴨子類型”來實現(xiàn)策略模式也很簡單,刪掉抽象基類就可以了。(這就是為什么抽象基類很少使用的原因,因為刪掉代碼也一樣正確啊。)有興趣的小伙伴可以自己嘗試一下代碼。
Python 中的協(xié)議舉例
Python 中有很多的協(xié)議,比如迭代器協(xié)議,任何實現(xiàn)了 __iter__ 和 __next__ 方法的對象都可稱之為迭代器,但對象本身是什么類型不受限制,這得益于鴨子類型。
from collections import Iterable from collections import Iterator class MyIterator: def __iter__(self): pass def __next__(self): pass print(isinstance(MyIterator(), Iterable)) print(isinstance(MyIterator(), Iterator))
輸出:
True
True
以上是“使用Python實現(xiàn)多態(tài)、協(xié)議和鴨子類型的代碼”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。