1. 程式人生 > 其它 >基類使用私有資料_【進階Python】第七講:介面與抽象基類

基類使用私有資料_【進階Python】第七講:介面與抽象基類

技術標籤:基類使用私有資料怎麼檢視抽象方法被哪些類繼承

3fac6b5d14e0c4deede326dd8d3096c6.png

點選藍字關注我

3fac6b5d14e0c4deede326dd8d3096c6.png
抽象基類(abstract base class,ABC),提到這個概念應該會馬上聯想到面向物件、繼承。作為繼承的一種,它擁有繼承中程式碼共享、提高程式碼的重用性等優點,此外它還擁有介面相關的一些特性,本文就來介紹一下Python抽象基類的使用。

—▼—

前言

抽象基類(abstract base class,ABC),提到這個概念應該會馬上聯想到面向物件繼承。作為繼承的一種,它擁有繼承中程式碼共享、提高程式碼的重用性等優點。例如,下面示例,
classAnimal(object):defeat(self,kind):print("{}eatfood....".format(kind))classDog(Animal):passclassCat(Animal):passdog=Dog()cat=Cat()dog.eat("dog")cat.eat("cat")#輸出dogeatfood....cateatfood....
狗(Dog)和貓(Cat)都屬於動物(Animal),它們有很多類似的屬性和動作,我們可以在父類中實現這些方法,在子類中直接繼承或者過載父類中的方法,這樣減少了程式碼的重複性,提高了程式碼的共享能力。 作為繼承的一種,抽象基類有用繼承的上述這些優點,但是它與普通的繼承也有不同之處,
  • 抽象基類不能例項化

  • 子類需要實現基類指定的抽象方法

看到這裡應該會意識到,抽象基類有一種介面的感覺,沒錯,抽象基類的出現主要是功能就是類似於Java等程式語言中的介面。 但是需要明確一點,Python語言中沒有interface這個概念,只是這是一種約定俗成的程式設計規範,就如同Python也沒有真實意義上的私有變數,我們在程式設計中可以規範的使用下劃線來表示某個變數為私有變數。 儘管Python中沒有介面這個關鍵字,但是抽象基類實現的功能主要圍繞介面在展開,因此,首先類比Java來闡述一下程式語言中介面的概念,然後介紹一下Python中如何實現抽象基類。

介面

介面(Interface)是物件公開方法的一種集合,在Java中通常以interface關鍵字來定義,介面雖然實現過程中和相似,但是卻具有不同的概念。具體而言,類與介面主要有以下幾點不同之處:

  • 類實現了物件的屬性和方法,而介面指定了使用該介面需要實現哪些方法

  • 類可以例項化,而介面不可以被例項化

  • 類中的方法可以是實現,介面中的方法都是抽象方法

抽象方法:抽象方法的概念是父類中只負責宣告該方法,但不具體實現這個方法,實現部分由繼承該類的子類負責實現。

如果覺得上述描述有點雲裡霧裡、對介面的概念依然不是非常清楚,不妨來試想一個場景:當你開發一個專案或者服務,你需要給上下游的元件提供介面,讓別人來呼叫你的程式介面(Application Programming Interface,API),上下游元件該怎麼樣才能達到想要的目的和你的元件無縫銜接?需要通過按照你介面中規定的抽象方法來實現,例如,你提供一個訪問網路請求的介面,你不會去實現host、username、password的註冊和傳送請求,這些需要呼叫的使用者去實現,你只需要規定:“呼叫者必須實現指定方法才能實現呼叫”即可。

抽象基類

雖然Python中抽象基類和介面概念非常相近,但是它們還是有一些不同之處,例如,

  • 介面需要被實現的子類完成介面中指定的所有方法,而抽象基類不是,抽象基類則沒有這麼嚴格的要求

  • 介面需要所有方法都是抽象方法,而抽象基類中有抽象方法,也有自己實現的方法

正是因為抽象基類和介面的不同之處使得介面之所以稱為介面、抽象基類之所以稱為抽象基類。

為什麼使用抽象基類?

前面鋪墊了這麼多,話說回來,為什麼需要抽象基類?

存在的即是合理的,抽象基類的存在自然有它的價值。當你學會一種程式語言的語法時,你可以輕鬆的完成一項功能的開發,但是如果希望把程式碼完成的更加優美高效,那麼就需要在設計模式等方面下一些功夫,抽象基類就是其中的一個選擇,抽象基類具有以下優點:

  • 處理繼承問題方面更加規範、系統

  • 明確呼叫之間的相互關係

  • 使得繼承層次更加清晰

  • 限定子類實現的方法

什麼是抽象基類?

前面已經介紹了很多有關介面的概念,抽象基類和介面有很多相似之處,例如需要包含抽象方法,不能被例項化,如果更加確切的定義抽象基類:必須包含一個抽象函式(純虛擬函式),它是一個不完整的類,它有已經被實現的方法,也有需要子類重寫的方法。

抽象基類使用場景

一項功能只有具有應用場景才能體現出它的價值,如果僅僅是為了看上去高逼格,那麼倒不如使用最簡單的條件、迴圈語句,沒必要花裡胡哨,讓程式碼變得難以維護、晦澀難懂。

抽象基類首先它具備普通繼承的功能,因此,在程式碼可以共用,或者需要獲取額外屬性的時候可以考慮使用抽象基類,例如,狗、貓、牛、羊這些動物有很多共有的屬性和方法,我們可以通過實現一個基類,讓每個特定的物件來繼承它,這樣不僅可以實現多型,還可以提高程式碼的複用能力。

當然,上述說的這些場景都偏重於普通繼承的優勢,而抽象基類的特別之處更加偏向於介面的特點,因此,它的使用場景和介面也有很多相通之處,例如我們開發一個系統,下面有若干個元件,每個元件都需要按照指定的規範來實現特定的方法,這時候我可以發揮抽象基類的限定功能的優勢

下面就結合這個場景來介紹Python中抽象基類的實現方法。

Python抽象基類

場景介紹

假如我們現在實現了一個數據中臺的開發,我們對外提供一個介面讓不同元件通過這個介面進行訪問資料庫,來讀取資料,我們給資料介面主要有2個功能,

  • 登入資料庫

  • 讀取資料

  • 執行SQL語句

可以想象,登入資料庫這個功能在不同元件之間可以共用,不同元件只需要提供host、user、passwd即可,至於讀取資料這是每個元件都必須單獨實現的,可以宣告為抽象方法,執行SQL語句也是每個子類需要實現的,可以宣告為抽象的靜態方法。

實現

Python標準庫中有一個模組abc可以實現抽象基類和抽象方法,它們的實現方式如下:

抽象基類:通過繼承abc模組中的ABC類來實現抽象基類。

抽象方法:通過裝飾器的方法來呼叫abc模組中abstractmethod方法來註解抽象基類的方法。

abstractmethod註解除了可以實現抽象方法外,還可以註解類方法(@classmethod)、靜態方法(@staticmethod)、屬性(@property)。

下面就先實現抽象基類,

fromabcimportABCfromabcimportabstractmethodclassDatabase(ABC):defregister(self,host,user,password):print("Host:{}".format(host))print("User:{}".format(user))print("Password:{}".format(password))print("RegisterSuccess!")@abstractmethoddefquery(self,*args):"""
傳入查詢資料的SQL語句並執行
"""@staticmethod@abstractmethoddefexecute(sql_string):"""
執行SQL語句
"""

從抽象基類Database的實現可以看出,它共包含3個方法,其中register是每個子類都需要的,直接實現在抽象基類裡,是一個普通的類方法。queryexecute只是在基類中進行類宣告,給出了描述,但並沒有實現,它限定了繼承Database的子類必須實現這兩個方法。

下面就來實現兩個元件(子類),

classComponent1(Database):def__init__(self,host,user,password):self.register(host,user,password)@staticmethoddefexecute(sql_string):print(sql_string)defquery(self,*args):sql_string="SELECTIDFROMdb_name"self.execute(sql_string)classComponent2(Database):def__init__(self,host,user,password):self.register(host,user,password)@staticmethoddefexecute(sql_string):print(sql_string)defquery(self,*args):sql_string="SELECTNAMEFROMdb_name"self.execute(sql_string)comp1=Component1("00.00.00.00","abc","000000")comp2=Component2("11.11.11.11","ABC","111111")comp1.query()comp2.query()#輸出結果Host:00.00.00.00User:abcPassword:000000RegisterSuccess!Host:11.11.11.11User:ABCPassword:111111RegisterSuccess!SELECTIDFROMdb_nameSELECTNAMEFROMdb_name

上述是通過Python標準庫中abc模組實現了抽象基類,其實在Python中collections中也實現了抽象基類,numbers中也定義了有關數字物件的抽象基類。可見,抽象基類在Python中佔據著至關重要的地位。

完整程式碼

本文所涉及的完整程式碼可以檢視github專案advance-python,也可以直接訪問下方連結,

https://github.com/Jackpopc/advance-python/blob/master/5-abstract%20.ipynb

END

9ed79a1fcd5df18e706b5b866b463043.png 84dc6829be1fdbdef6f0aedbe7383040.png 有趣的靈魂在等你

長按掃碼可關注

相關文章 【進階Python】第一講: 開篇 【進階Python】第二講: 裝飾器 【進階Python】第三講: 類的特殊方法(上篇) 【進階Python】第四講: 類的特殊方法(下篇) 【進階Python】第五講: 迭代器與生成器 【進階Python】第六講: 單例模式的妙用文章好看就點這裡 d77986b213cf1507d99acf92bc480212.gif