亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何使用Python基于接口編程的方法實現(xiàn)

 更新時間:2021年11月17日 09:07:11   作者:somenzz  
本文主要介紹了如何使用Python基于接口編程,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

軟件行業(yè),唯一不變的就是變化。產(chǎn)品經(jīng)理會變,產(chǎn)品需求會變,代碼同樣要跟著變。

不同的代碼設計,變化所帶來的工作量更是不同,有的每改一次需求,近乎一次重構,而有的只需要修改一個配置文件,或者在類里添加一行代碼。當然比較好的代碼設計,由于有著良好的可擴展性,高內(nèi)聚,低耦合,因而易維護, 以少變應萬變。如果才能有好的代碼設計,就需要我們學習設計模式。今天為你分享的是在Python中,如何基于接口編程。

1994 年 GoF 的《設計模式》一書中有一個重要的原則就是:基于接口而非實現(xiàn)編程,英文源文是「Program to an interface,not an implementaion」,這里的所說的 interface,并不是特定編程語言中的接口,它是語言無關的,是指開發(fā)者提供給使用者的一個功能列表,理解了這一點非常重要。接口在 java 語言中是有關鍵字 interface 來實現(xiàn)的,java 不支持類的多重繼承,但支持接口的多重繼承,所在 java 開發(fā)者對接口非常熟悉了,Python 其實完全不需要 Java 那樣的設計,但可以借鑒接口的優(yōu)點。

先通過一個實例來了解下接口到底解決什么問題。

比如你正在實現(xiàn)一個圖片上傳功能,目前采用七牛云來存儲,你的類可能是這樣的。

class QnyImageStore(object):

    def getToken():
        pass

    def upload_qny(self,image):
        print("Qny upload.")
        #do something
    
    def download_qny(self,image):
        print("Qny download.")
        #do something

實際的開發(fā)中,代碼會有很多行,函數(shù)也不止三個,它被成百上千個地方被調(diào)用,分散在好幾百個文件中。 過了一段時間,公司自建了私有云,要求不能再使用七牛云了,要改成自己的云存儲,于是你不得不重新寫一個類:

class OwnImageStore(object):

    def upload_own(self,image):
        print("Qny upload.")
        #do something
    
    def download_own(self,image):
        print("Qny download.")
        #do something

然后你在使用七牛去的地方,都進行替換,還要替換函數(shù)的名稱,最后還要多次測試,生活哪一處沒有考慮到,運行報錯。好不容易改好了,突然有一天,需求又變了,由于自己的云服務經(jīng)常出問題,于是要換阿里云。經(jīng)過上次的一翻痛苦折騰,看到這次又要改,直接吐血。

其實問題就在于你寫的代碼不夠通用,命名不夠抽象。假如你的類的函數(shù)命名使用 upload,download 這樣,那么你修改的代碼量可能會減少到一半,只替換一下類名就可以了。實際上,我們可以使用接口來減少代碼的改動量:通過接口和實現(xiàn)相分離的模式,封裝不穩(wěn)定的實現(xiàn),暴露穩(wěn)定的接口。上下游系統(tǒng)在使用我們開發(fā)的功能時,只需要使用接口中聲明的函數(shù)列表,這樣當實現(xiàn)發(fā)生變化的時候,上游系統(tǒng)的代碼基本上不需要做改動,以此來降低耦合性,提高擴展性。下面就該問題,提供一種基于接口的代碼實現(xiàn)方式。

定義一個接口

from abc import ABCMeta, abstractmethod

class ImageStore(metaclass = ABCMeta):
    
    @abstractmethod
    def upload(self,image): 
        pass
        #raise NotImplementedError

    @abstractmethod
    def download(self,image): 
        pass
        #raise NotImplementedError

定義了該接口之后,任何繼承該接口的類要想正確的使用,必須重寫 upload 和 download 方法,否則均會拋出異常,這里我們不需要自己在接口中拋出異常,標準庫 abc 已經(jīng)為我們做好了這些工作。

定義類,繼承接口

目的其實是是為了強制約束,也就是說必須實現(xiàn) upload 和 download 方法,在編譯時進行檢查,確保程序的健壯。

class OwnImageStore2(ImageStore):

    def upload(self,image):
        print("Own upload.")
        #do something
    
    def download(self,image):
        print("Own download.")
        #do something

class QnyImageStore2(ImageStore):

    def getToken():
        pass

    def upload(self,image):
        print("Qny upload.")

    def download(self,image):
        print("Qny download.")
        #do something

接下來,我們定義一個接口,可以自動的根據(jù)類型來選擇調(diào)用對應對象的方法。

class UsedStore(object):

    def __init__(self, store):
        if not isinstance(store, ImageStore): raise Exception('Bad interface')
        self._store = store

    def upload(self):
        self._store.upload('image')

    def download(self):
        self._store.download('image')

最后,我們可以在配置文件中指明我們使用的是哪個具體的接口:

#在其他文件中,應該這樣調(diào)用
img = QnyImageStore2()
# img = OwnImageStore2() 把這些放在配置文件中,只需要更新配置文件就可以替換 
store = UsedStore(img)
store.upload()
store.download()

這樣,后面再增加新的圖片存儲,我們只需要添加相應的類,繼承接口,并修改下配置文件即可,減輕大量的代碼修改工作。

Python 抽象基類的介紹 (PEP3119)

python 標準庫 abc,全稱是Abstract Base Classes,它提供以下功能:

  • 一種重載isinstance()和issubclass()的方法
  • 一個新的模塊abc作為“Abstract Base Classes支持框架”。它定義了一個用于abc的元類和一個可以用來定義抽象方法的裝飾器
  • 容器和迭代器的特定抽象基類,將被添加到 collections 模塊

基本原理:

在面向?qū)ο蟪绦蛟O計領域,與對象交互的設計模式可以分為兩個基本類別,即“調(diào)用”和“檢查”。

調(diào)用是指通過調(diào)用對象的方法與對象進行交互。 通常,這會與多態(tài)性結合使用,因此調(diào)用給定方法可能會根據(jù)對象的類型運行不同的代碼。

檢查是指外部代碼(在對象的方法之外)檢查該對象的類型或?qū)傩裕⒏鶕?jù)該信息來決定如何處理該對象的能力。

兩種使用模式均服務于相同的通用目的,即能夠以統(tǒng)一的方式支持處理多種多樣且可能新穎的對象,但同時允許為每種不同類型的對象定制處理決策。

在經(jīng)典的 OOP 理論中,調(diào)用是首選的設計模式,并且不鼓勵檢查,因為檢查被認為是較早的過程編程風格的產(chǎn)物。 但是,實際上,這種觀點過于教條和僵化,導致了某種設計僵化,與諸如 Python 之類的語言的動態(tài)特性大相徑庭。

特別是,通常需要以對象類的創(chuàng)建者無法預期的方式處理對象。 內(nèi)置到滿足該對象的每個可能用戶需求的每個對象方法中,并非總是最佳的解決方案。 而且,有許多強大的調(diào)度哲學與嚴格地封裝在對象中的經(jīng)典OOP行為要求形成鮮明對比,例如規(guī)則或模式匹配驅(qū)動的邏輯

另一方面,經(jīng)典的 OOP 理論家對檢查的批評之一是缺乏形式主義和被檢查內(nèi)容的特殊性質(zhì)。 在諸如 Python 這樣的語言中,幾乎可以通過外部代碼反映并直接訪問對象的任何方面,有很多不同的方法來測試對象是否符合特定的協(xié)議。 例如,如果詢問“此對象是否是可變序列容器?”,則可以尋找“列表”的基類,或者可以尋找名為“ getitem”的方法。 但是請注意,盡管這些測試看似顯而易見,但它們都不正確,因為其中一個會產(chǎn)生假陰性,而另一個會產(chǎn)生假陽性。

普遍同意的補救措施是對測試進行標準化,并將其分組為正式形式。 通過繼承機制或其他某種方式,通過與每個類關聯(lián)一組標準的可測試屬性,最容易做到這一點。 每個測試都帶有一組承諾:它包含有關類的一般行為的承諾,以及有關其他可用的類方法的承諾。

PEP為組織這些測試提出了一種特殊的策略,稱為抽象基類(ABC)。 ABC只是添加到對象的繼承樹中的Python類,以將對象的某些功能發(fā)送給外部檢查器。 使用isinstance()完成測試,并且特定ABC的存在意味著測試已通過。

此外,ABC定義了建立該類型特征行為的最少方法集。 根據(jù)對象的ABC類型區(qū)分對象的代碼可以相信,這些方法將始終存在。 這些方法中的每一個都附帶有ABC文檔中描述的廣義抽象語義定義。 這些標準的語義定義不是強制性的,但強烈建議使用。

像Python中的所有其他內(nèi)容一樣,這些承諾屬于紳士協(xié)議的性質(zhì),在這種情況下,這意味著盡管該語言確實執(zhí)行了ABC中做出的某些承諾,但具體類的實現(xiàn)者必須確保 剩下的保留下來。

看完上面的描述,你可以簡單的理解為,ABC 是一個基類,繼承它,你可以寫一個類似于 java 的接口,接口中的方法將始終存在,可以放心使用,不需要再進行探測。

PEP3119 還給了樣例代碼讓你理解:

from abc import ABCMeta, abstractmethod

class A(metaclass=ABCMeta):
    @abstractmethod
    def foo(self): pass

A()  # raises TypeError

class B(A):
    pass

B()  # raises TypeError

class C(A):
    def foo(self): print(42)

C()  # works

多的不說了,希望你可以正確地使用 ABC,同時強烈推薦,學習 Python,就看 Python 的官方文檔和 PEP 提案,這里有最權威的講解。

此外,設置模式也是非常重要的編程之術和編程之道,它是基本功,基本功如果不夠,把一臺戰(zhàn)斗機放你面前,你都不知道如何欣賞和品味。

掌握了設計模式,再看別人的代碼,你會擁有火眼金睛,哪些是戰(zhàn)斗機,哪些是拖拉機,對自己的學習和提升也非常有幫助,寫的代碼也會更加具有可維護性,可讀性,可擴展性,靈活性。

到此這篇關于如何使用Python基于接口編程的方法實現(xiàn)的文章就介紹到這了,更多相關Python基于接口編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Python 文本滾動播放器的實現(xiàn)代碼

    Python 文本滾動播放器的實現(xiàn)代碼

    這篇文章主要介紹了Python 文本滾動播放器的實現(xiàn)代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • pytorch 實現(xiàn)在預訓練模型的 input上增減通道

    pytorch 實現(xiàn)在預訓練模型的 input上增減通道

    今天小編就為大家分享一篇pytorch 實現(xiàn)在預訓練模型的 input上增減通道,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • jupyter notebook運行代碼沒反應且in[ ]沒有*

    jupyter notebook運行代碼沒反應且in[ ]沒有*

    本文主要介紹了jupyter notebook運行代碼沒反應且in[ ]沒有*,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 詳解Django+Uwsgi+Nginx的生產(chǎn)環(huán)境部署

    詳解Django+Uwsgi+Nginx的生產(chǎn)環(huán)境部署

    這篇文章主要介紹了Django + Uwsgi + Nginx 的生產(chǎn)環(huán)境部署,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • Pycharm無法使用已經(jīng)安裝Selenium的解決方法

    Pycharm無法使用已經(jīng)安裝Selenium的解決方法

    今天小編就為大家分享一篇Pycharm無法使用已經(jīng)安裝Selenium的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • Mac中升級Python2.7到Python3.5步驟詳解

    Mac中升級Python2.7到Python3.5步驟詳解

    本篇文章主要介紹了Mac中升級Python2.7到Python3.5步驟詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • Python中map函數(shù)的技巧分享

    Python中map函數(shù)的技巧分享

    在Python中,map()是一個內(nèi)置函數(shù),這篇文章將從基礎的使用方法到高級的技巧,全面介紹Python中map()方法的使用,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-07-07
  • 解決Python中pandas讀取*.csv文件出現(xiàn)編碼問題

    解決Python中pandas讀取*.csv文件出現(xiàn)編碼問題

    很多朋友在使用Python中pandas讀取csv文件時,出現(xiàn)編碼格式問題,接下來通過本文給大家分享解決Python中pandas讀取*.csv文件出現(xiàn)編碼問題,需要的朋友可以參考下
    2019-07-07
  • 探索Python函數(shù)調(diào)用為何加速代碼執(zhí)行原理

    探索Python函數(shù)調(diào)用為何加速代碼執(zhí)行原理

    Python 作為一種解釋型語言,其執(zhí)行速度相對于編譯型語言可能會較慢,然而,在Python中,通常觀察到代碼在函數(shù)中運行得更快的現(xiàn)象,這個現(xiàn)象主要是由于函數(shù)調(diào)用的內(nèi)部優(yōu)化和解釋器的工作方式導致的,本文將深入探討這個現(xiàn)象,并通過詳細的示例代碼進行解釋
    2024-01-01
  • 基于PyQt5實現(xiàn)狀態(tài)欄(statusBar)顯示和隱藏功能

    基于PyQt5實現(xiàn)狀態(tài)欄(statusBar)顯示和隱藏功能

    這篇文章主要為大家詳細介紹了如何利用PyQt5實現(xiàn)狀態(tài)欄顯示和隱藏功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-08-08

最新評論