欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2019年05月05日 11:40:37   投稿:mrr  
問(wèn)起面向?qū)ο蟮娜筇匦?,幾乎每個(gè)人都能對(duì)答如流:封裝、繼承、多態(tài)。今天我們就要來(lái)說(shuō)一說(shuō)Python實(shí)現(xiàn)多態(tài)、協(xié)議和鴨子類型,感興趣的朋友跟隨小編一起看看吧

多態(tài)

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

所謂多態(tài):就是指一個(gè)類實(shí)例的相同方法在不同情形有不同表現(xiàn)形式。多態(tài)機(jī)制使具有不同內(nèi)部結(jié)構(gòu)的對(duì)象可以共享相同的外部接口。這意味著,雖然針對(duì)不同對(duì)象的具體操作不同,但通過(guò)一個(gè)公共的類,它們(那些操作)可以通過(guò)相同的方式予以調(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# 等語(yǔ)言中,實(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 語(yǔ)言沒有 interface 關(guān)鍵字,就是說(shuō),Python 里沒有像 java、C# 一樣的接口。

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

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

協(xié)議和鴨子類型

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

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

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

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

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

用“鴨子類型”來(lá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é)語(yǔ)

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

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

相關(guān)文章

最新評(píng)論