国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

詳細介紹Python的鴨子類型

2019-11-25 16:34:24
字體:
來源:轉載
供稿:網友

鴨子類型基本定義

首先Python不支持多態,也不用支持多態,python是一種多態語言,崇尚鴨子類型。

以下是維基百科中對鴨子類型得論述:

在程序設計中,鴨子類型(英語:duck typing)是動態類型的一種風格。在這種風格中,一個對象有效的語義,不是由繼承自特定的類或實現特定的接口,而是由當前方法和屬性的集合決定。這個概念的名字來源于由James Whitcomb Riley提出的鴨子測試,“鴨子測試”可以這樣表述:

“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。”

在鴨子類型中,關注的不是對象的類型本身,而是它是如何使用的。例如,在不使用鴨子類型的語言中,我們可以編寫一個函數,它接受一個類型為鴨的對象,并調用它的走和叫方法。在使用鴨子類型的語言中,這樣的一個函數可以接受一個任意類型的對象,并調用它的走和叫方法。如果這些需要被調用的方法不存在,那么將引發一個運行時錯誤。任何擁有這樣的正確的走和叫方法的對象都可被函數接受的這種行為引出了以上表述,這種決定類型的方式因此得名。

鴨子類型通常得益于不測試方法和函數中參數的類型,而是依賴文檔、清晰的代碼和測試來確保正確使用。從靜態類型語言轉向動態類型語言的用戶通常試圖添加一些靜態的(在運行之前的)類型檢查,從而影響了鴨子類型的益處和可伸縮性,并約束了語言的動態特性。

python中的具體實現

下面的代碼就是一個簡單的鴨子類型

class duck():  def walk(self):    print('I walk like a duck')  def swim(self):    print('i swim like a duck')class person():  def walk(self):    print('this one walk like a duck')   def swim(self):    print('this man swim like a duck')

對于一個鴨子類型來說,我們并不關心這個對象的類型本身或是這個類繼承,而是這個類是如何被使用的。我們可以通過下面的代碼來調用這些類的方法。

def watch_duck(animal):  animal.walk()  animal.swim()small_duck = duck()watch_duck(small_duck)output >> I walk like a ducki swim like a duckduck_like_man = person()watch_duck(duck_like_man)output >> this one walk like a duckthis man swim like a duckclass Lame_Foot_Duck():  def swim(self):    print('i am lame but i can swim')lame_duck = Lame_Foot_Duck()watch_duck(lame_duck)output >>AttributeError: Lame_Foot_Duck instance has no attribute 'walk'

watch_duck函數接收這個類的對象,然后并沒有檢查對象的類型,而是直接調用這個對象的走和游的方法,如果所需要的方法不存在就報錯。

具體在python中鴨子類型的體現如下面的代碼所示

class CollectionClass():  lists = [1,2,3,4]  def __getitem__(self, index):    return self.lists[index]iter_able_object = CollectionClass()class Another_iterAbleClass():  lists=[1,2,3,4]  list_position = -1  def __iter__(self):    return self  def next(self): #還有更簡單的實現,使用生成器或迭代器什么的:)    self.list_position += 1    if self.list_position >3:      raise StopIteration    return self.lists[self.list_position]another_iterable_object=Another_iterAbleClass()print(iter_able_object[1])print(iter_able_object[1:3])output>>2[2, 3]another_iterable_object[2]output>>Traceback (most recent call last): File "/Users/steinliber/a.py", line 32, in <module>  another_iterable_object[2]TypeError: 'Another_iterAbleClass' object does not support indexingprint(next(another_iterable_object))output>>1print(next(another_iterable_object))output>>2print(next(iter_able_object))output>>Traceback (most recent call last): File "/Users/steinliber/a.py", line 29, in <module>  print(next(iter_able_object))TypeError: IterAbleClass object is not an iterator

在python把上述代碼的實現方法叫做protocol(協議),這些protocol可以看作是通知型的接口,它規定了調用方使用該功能要調用對象的哪些方法,被調用方要實現哪些方法才能完成這個功能。它和java中的接口區別在于java中的接口功能實現需要通過繼承,繼承的類必須實現接口中的所有的抽象方法,所以在Java中強調的是類型的概念,而python中的protocol更多的是通知性的,一個函數規定要實現某個功能需要調用傳入對象的哪些方法,所有實現這些方法的類就可以實現這個功能。

具體從上面兩個類來說,第一個類實現了__getitem__方法,那python的解釋器就會把它當做一個collection,就可以在這個類的對象上使用切片,獲取子項等方法,第二個類實現了__iter__next方法,python就會認為它是一個iterator,就可以在這個類的對象上通過循環來獲取各個子項。一個類可以實現它有能力實現的方法,并只能被用于在它有意義的情況下。

這兩個類和上面的鴨子類相比較,其實用于切邊的[](它其實調用的是python的slice函數)和用于循環的iter()就相當于watch_duck函數,這些函數都接收任意類的對象,并調用實現功能所需要的對象中的方法來實現功能,若該函數中調用的方法對象里面不存在,就報錯。

從上面可以看出,python鴨子類型的靈活性在于它關注的是這個所調用的對象是如何被使用的,而沒有關注對象類型的本身是什么。所以在python中使用isinstance來判斷傳入參數的類型是不提倡的,更pythonic的方法是直接使用傳入的參數,通過try,except來處理傳入參數不符合要求的情況。我們應該通過傳入對象的能力而不是傳入對象的類型來使用該對象。

總結

以上就是Python鴨子類型的詳細介紹,本文內容介紹的還是很詳細的,希望對大家學習python能有一定的幫助,如果有疑問大家可以留言交流。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 定结县| 无棣县| 黎川县| 鸡泽县| 二手房| 五寨县| 姜堰市| 辽宁省| 虎林市| 洪洞县| 平湖市| 昌吉市| 盘锦市| 文安县| 大丰市| 思南县| 安岳县| 蓬莱市| 天祝| 南投县| 板桥市| 洞口县| 遂川县| 睢宁县| 鄂温| 德州市| 峨边| 苏州市| 和静县| 宝清县| 七台河市| 南阳市| 江源县| 遂溪县| 广南县| 山阳县| 罗山县| 定远县| 霍山县| 阿巴嘎旗| 涪陵区|