Python基礎之接口——從協議到抽象基類

導語:本文章記錄了本人在學習Python基礎之面向對象篇的重點知識及我的心得,打算入門Python的朋友們能夠來一塊兒學習並交流。

本文重點:安全

一、協議是Python中非正式的接口;
二、瞭解抽象基類的基本概念以及標準庫中的抽象基類;
三、掌握抽象基類的使用方法。

1、協議的高度動態本性

一、協議與接口的基本概念

協議:是Python中非正式的接口,是令Python這種動態類型語言實現多態的方式。
接口:泛指實體把本身提供給外界的一種抽象化物(能夠爲另外一實體),用以由內部操做分離出外部溝通方法,使其能被內部修改而不影響外界其餘實體與其交互的方式。
類的接口:類實現或繼承的公開屬性(方法或數據屬性),包括特殊方法,如__getitem__或__add__。app

二、協議是非正式的

協議是非正式的,只由文檔和約定定義,不具有強制性。
以序列協議爲例,假設咱們想實現迭代以及in運算,一般須要__iter__和__contains__方法,但事實上只實現__getitem__方法也能夠。緣由在於當Python發現沒有__iter__和__contains__可用時,會轉而調用__getitem__方法設法讓迭代和in運算符可用。
小結:部分實現協議是有用的。ssh

三、使用猴子補丁在運行時實現協議

在運行時修改類或模塊而不改動源碼,從而實現目標協議接口的操做就是打猴子補丁。函數

2、抽象基類

一、基本概念

鴨子類型(duck typing):不關注對象的類型,而是關注對象具備的行爲(方法)。鴨子類型像多態同樣工做,可是沒有繼承。
在鴨子類型中,協議風格的接口與繼承徹底沒有關係,實現同一個協議的各個類是相互獨立的。學習

白鵝類型(goose typing):只要cls是抽象基類,即cls的元類是abc.ABCMeta,就可使用isinstance(obj,cls)。spa

抽象基類(abstract base class,ABC):抽象基類就是類裏定義了純虛成員函數的類。純虛函數只提供了接口,並無具體實現。抽象基類不能被實例化(不能建立對象),一般是做爲基類供子類繼承,子類中重寫虛函數,實現具體的接口。簡言之,ABC描述的是至少使用一個純虛函數的接口,從ABC派生出的類將根據派生類的具體特徵,使用常規虛函數來實現這種接口。code

二、標準庫中的抽象基類

(1)collections.abc中抽象基類
collections.abc模塊中各個抽象基類的UML類圖以下所示:
collections.abc模塊中各個抽象基類的UML類圖對象

  • Iterable、 Container 和 Sized
    各個集合應該繼承這三個抽象基類, 或者至少實現兼容的協議。
    Iterable 經過 __iter__ 方法支持迭代;
    Container 經過__contains__ 方法支持 in 運算符;
    Sized 經過 __len__ 方法支持len() 函數。
  • Sequence、 Mapping 和 Set
    這三個是主要的不可變集合類型, 並且各自都有可變的子類。
  • MappingView
    在 Python 3 中, 映射方法 .items()、 .keys() 和 .values() 返回的對象分別是 ItemsView、 KeysView 和 ValuesView 的實例。 前兩個類還從 Set 類繼承了豐富的接口,涉及集合的所有運算符。
  • Callable 和 Hashable
    這兩個抽象基類與集合沒有太大的關係,只不過由於collections.abc 是標準庫中定義抽象基類的第一個模塊, 而它們又過重要了,所以才把它們放到 collections.abc 模塊中。Callable 或 Hashable 的子類很是少見。這兩個抽象基類的主要做用是爲內置函數 isinstance 提供支持,以一種安全的方式判斷對象能不能調用或散列。
  • Iterator
    是 Iterable 的子類。

(2)numbers包中的數字塔
按照自上而下的線性結構,Number是位於最頂端的超類,詳細排序以下:排序

  • Number
  • Complex
  • Real
  • Rational
  • Integral

例如,檢查一個數是不是整數,可使用isinstance(x,numbers.Integral)。繼承

3、抽象基類的使用

一、經過繼承聲明抽象基類

聲明抽象基類最簡單的方式是繼承abc.ABC或其餘抽象基類:Class Student(abc.ABC)
注意:在Python3.0~3.3之間,繼承抽象基類的語法是:Class Student(metaclass=abc.ABCMeta)。

二、判斷子類是否符合接口定義

在定義抽象基類的子類時,子類須要將繼承的抽象基類中的抽象方法具體實現。

三、聲明虛擬子類實現抽象基類的接口

虛擬子類:指的是不經過繼承而利用註冊把一個類變成抽象基類的子類。
註冊虛擬之類的方式是調用register方法,語法是@抽象基類名稱.register。
經註冊後的虛擬子類能夠被issubclass和isinstance等函數識別,可是註冊的類不會從抽象基類中繼承任何方法或屬性。具體可經過類屬性__mro__查看類的真實繼承關係。

4、其它

一、抽象基類中聲明抽象類方法須要使用@abc.abstractmethod標記,而且在@abc.abstractmethod和def之間不能有其餘裝飾器。二、內省類的繼承關係的方法:__subclasses__():返回類的直接子類列表,不含虛擬子類。__abcregistry:抽象基類獨有的屬性,是抽象類註冊的虛擬子類的弱引用。三、__subclasshook__:令抽象基類識別沒有進行子類化和註冊的類,此方法在abc.Sized中有應用。

相關文章
相關標籤/搜索