黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

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

系統(tǒng) 2099 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 提出的鴨子測(cè)試。

初次看到這個(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)策略模式也很簡(jiǎ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)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

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

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論