亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python實(shí)現(xiàn)多態(tài)、協(xié)議和鴨子類型的代碼詳解

系統(tǒng) 1782 0

多態(tài)

問起面向?qū)ο蟮娜筇匦裕瑤缀趺總€(gè)人都能對(duì)答如流: 封裝、繼承、多態(tài) 。今天我們就要來說一說 Python 中的多態(tài)。

所謂多態(tài):就是指一個(gè)類實(shí)例的相同方法在不同情形有不同表現(xiàn)形式。多態(tài)機(jī)制使具有不同內(nèi)部結(jié)構(gòu)的對(duì)象可以共享相同的外部接口。這意味著,雖然針對(duì)不同對(duì)象的具體操作不同,但通過一個(gè)公共的類,它們(那些操作)可以通過相同的方式予以調(diào)用。

我在《Python 中的設(shè)計(jì)模式詳解之:策略模式》一文中詳細(xì)描述了策略模式的實(shí)現(xiàn),而策略模式就是典型的多態(tài)應(yīng)用。

之前的代碼我就不貼了,大家可以去原文中查看。我依然還是以商品折扣的經(jīng)典舉例。策略模式一文中,傳統(tǒng)的策略模式實(shí)現(xiàn)方式我也是用 Python 代碼實(shí)現(xiàn)的,在 java 或 C# 等語言中,實(shí)現(xiàn)方式也差不多。以下是 C# 代碼,我只列了個(gè)架子:

            
interface Promotion
{
 double discount(Order order);
}
class FidelityPromo : Promotion // 第一個(gè)具體策略
{
 // 為積分為1000或以上的顧客提供5%折扣
 public double discount(Order order)
 {
  ...
 }
}
class BulkItemPromo : Promotion // 第二個(gè)具體策略
{
 //單個(gè)商品為20個(gè)或以上時(shí)提供10%折扣
 public double discount(Order order)
 {
  ...
 }
}
class LargeOrderPromo : Promotion // 第三個(gè)具體策略
{
 //訂單中的不同商品達(dá)到10個(gè)或以上時(shí)提供7%折扣
 public double discount(Order order)
 {
  ...
 }
}
          

可以看到,首先要有一個(gè)接口(Promotion),然后各個(gè)策略去實(shí)現(xiàn)這個(gè)接口。然而,Python 語言沒有 interface 關(guān)鍵字,就是說,Python 里沒有像 java、C# 一樣的接口。

在策略模式一文的實(shí)現(xiàn)中,使用了抽象基類(Abstract Base Class,ABC)來實(shí)現(xiàn)接口,這主要是為了寫法上看起來和 java、C# 等語言更加的像,易于有這些語言基礎(chǔ)的同學(xué)理解和對(duì)比。

抽象基類是在 Python 語言誕生 15 年后,Python 2.6 才引入的。這里我們不詳細(xì)介紹抽象基類,因?yàn)榧幢悻F(xiàn)在也很少有代碼使用抽象基類。對(duì)于多態(tài),Python 有更好的實(shí)現(xiàn)方式――鴨子類型(duck typing)。

協(xié)議和鴨子類型

所謂 鴨子類型 就是:如果一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么它就是鴨子。這個(gè)概念的名字來源于 James Whitcomb Riley 提出的鴨子測試。

初次看到這個(gè)描述的小伙伴一定一頭霧水,為了理解鴨子類型,我們不得不提到另一個(gè)名詞――協(xié)議。

在面向?qū)ο缶幊讨校瑓f(xié)議是非正式的接口,是一組方法,只由文檔和約定定義,因此,協(xié)議不能像正式接口那樣施加強(qiáng)制性約束。而 Python 的哲學(xué)就是盡量支持基本協(xié)議。

翻譯成人話,就是:Python 中沒有接口,在需要使用接口的地方,就用協(xié)議代替。所謂協(xié)議,其實(shí)就是一組方法,和接口中定義的方法一個(gè)意思。只不過協(xié)議是不是強(qiáng)制性的約定,如果你不遵守協(xié)議,那么也沒關(guān)系,運(yùn)行時(shí)報(bào)錯(cuò)就是了。

這樣就好理解鴨子類型了,“如果一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子” 這就表示已經(jīng)遵守了協(xié)議,“那么它就是鴨子”,意味著你可以在其他用到“鴨子”的地方,用“這只鳥”替換。這不就是多態(tài)嗎?

用“鴨子類型”來實(shí)現(xiàn)策略模式也很簡單,刪掉抽象基類就可以了。(這就是為什么抽象基類很少使用的原因,因?yàn)閯h掉代碼也一樣正確啊。)有興趣的小伙伴可以自己嘗試一下代碼。

Python 中的協(xié)議舉例

Python 中有很多的協(xié)議,比如迭代器協(xié)議,任何實(shí)現(xiàn)了 __iter__ 和 __next__ 方法的對(duì)象都可稱之為迭代器,但對(duì)象本身是什么類型不受限制,這得益于鴨子類型。

            
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

結(jié)語

鴨子類型是編程語言中動(dòng)態(tài)類型語言中的一種設(shè)計(jì)風(fēng)格,一個(gè)對(duì)象的特征不是由父類決定,而是通過對(duì)象的方法決定的。

Python 不是不支持多態(tài),而是 Python 本身就是一門多態(tài)的語言。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 可以直接看的毛片 | 在线免费福利 | 深夜影院老司机69影院 | 一级片免费网站 | 鲁丝丝国产一区二区 | 亚洲韩精品欧美一区二区三区 | 红色一级毛片 | 欧美第一页在线观看 | 伊人网伊人网 | 精品久久久久久中文字幕无碍 | 狠狠色噜噜狠狠狠合久 | 日韩欧美一中字暮 | 福利在线看片 | 国产美女亚洲精品久久久毛片 | 久久伊人操 | 欧美性大战久久久久久久蜜桃 | 亚洲第一区视频在线观看 | 亚洲精品成人久久 | 国产福利区一区二在线观看 | 亚洲精品久久久久久久777 | 国产欧美精品一区二区三区 | 又粗又大的机巴好爽7 | 成人欧美一区二区三区黑人3p | 999热在线精品观看全部 | 久久精品成人一区二区三区 | 亚洲精品久久久久综合中文字幕 | 关婷哪一级毛片高清免费看 | www.777奇米| 最近中文日本字幕免费完整 | 久热免费视频 | 亚洲精品午夜久久久伊人 | 日韩欧美 在线播放 | 国产精品久久久久9999 | 久久久久久久爱综合 | 免费一级黄色片 | 国产精品成人网 | 一个色的综合 | 亚洲精品动漫3d一区二区 | 日本在线一区二区 | 午夜视频福利在线观看 | 咪咪爱在线观看 |