Python內置類型(5)--迭代器類型

来源:http://www.cnblogs.com/sesshoumaru/archive/2017/12/18/python-iterator.html
-Advertisement-
Play Games

指能夠被內置函數`next`調用並不斷返回下一個值,直到最後拋出`StopIteration`錯誤表示無法繼續返回下一個值的對象稱為迭代器(`Iterator`) ...


指能夠被內置函數next調用並不斷返回下一個值,直到最後拋出StopIteration錯誤表示無法繼續返回下一個值的對象稱為迭代器(Iterator)

其實以上的說法只是俠義上的迭代器的定義,在python中,迭代器還需要實現可迭代介面(Iterable),可迭代介面需要返回的是一個迭代器對象,這樣迭代器就能夠被for語句進行迭代。

迭代器對象初步認知

python中,沒有內置迭代器類型的對象,但是可以通過內置函數iterstrtuplelistdictset等類型轉換成一個迭代器對象。

>>> s = 'abc'
>>> next(s)
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
    next(s)
TypeError: 'str' object is not an iterator
# 以上報錯信息可以看出`str`不是迭代器
>>> it_s = iter(s)
>>> next(it_s)
'a'
>>> next(it_s)
'b'
>>> next(it_s)
'c'
>>> next(it_s)
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
    next(it_s)
StopIteration
# 以上報錯信息可以看出`iter(str)`是迭代器

通過不斷的調用next(iterator)方法來獲取下一個值,這樣其實不怎麼方便,python提供了更為簡潔的方法,即for迴圈。for迴圈每執行一次即相當於調用了一次next(iterator)方法,直到捕獲到StopIteration異常退出迴圈。

>>> it_s = iter(s)
>>> for c in it_s:
    print(c)

a
b
c

# 以上的例子是使用for迴圈遍歷迭代器

模塊collections中的類型Iterator就是迭代器的抽象基類,所有的迭代器都是Iterator的實例。即如果一個對象是Iterator的實例,則說明此對象是迭代器。

from collections import Iterator

>>> isinstance(s,Iterator)
False

>>> isinstance(it_s,Iterator)
True

# 以上信息證實了`str`不是迭代器,而`iter(str)`是迭代器

如何自己實現一個迭代器

根據python鴨子類型的特性,我們自定義的類型中,只要實現了__next()__方法,該方法在每次被調用時不斷返回下一個值,直到無法繼續返回下一個值時拋出StopIteration異常即可(next(iterator)實際上調用的是iterator內部的__next()__方法)。

定義自己的迭代器

>>> class MyIter():

    def __init__(self,max_value):
        self.current_value = 0
        self.max_value = max_value

    def __next__(self):
        if self.current_value < self.max_value:
            result = self.current_value
            self.current_value += 1
            return result
        else:
            raise StopIteration

驗證next方法是否不停返回下一個值

>>> my_iter = MyIter(3)
>>> next(my_iter)
0
>>> next(my_iter)
1
>>> next(my_iter)
2
>>> next(my_iter)
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    next(my_iter)
StopIteration

驗證對象是否可以用於for迴圈

>>> my_iter = MyIter(3)
>>> for i in my_iter:
    print(i)

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    for i in my_iter:
TypeError: 'MyIter' object is not iterable

驗證對象是否是Iterator實例

>>> from collections import Iterator
>>> isinstance(my_iter,Iterator)
False

從上面的驗證可以看出僅僅實現__next()__方法的對象還不是迭代器,真正的迭代器還需要實現一個可迭代介面Iterable

IteratorIterable的關係

在模塊collections中的類型Iterator就是迭代器的抽象基類,其實它裡面還定義了類型Iterable,它是可迭代對象的抽象基類。先分別通過help命令查看他們的定義:

>>> from collections import Iterator, Iterable
>>> help(Iterator)
Help on class Iterator in module collections.abc:

class Iterator(Iterable)
 |  Method resolution order:
 |      Iterator
 |      Iterable
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __iter__(self)
 |  
 |  __next__(self)
 |      Return the next item from the iterator. When exhausted, raise StopIteration
 |  
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |  
 |  __subclasshook__(C) from abc.ABCMeta
 |      Abstract classes can override this to customize issubclass().
 |      
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __abstractmethods__ = frozenset({'__next__'})

>>> help(Iterable)
Help on class Iterable in module collections.abc:

class Iterable(builtins.object)
 |  Methods defined here:
 |  
 |  __iter__(self)
 |  
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |  
 |  __subclasshook__(C) from abc.ABCMeta
 |      Abstract classes can override this to customize issubclass().
 |      
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __abstractmethods__ = frozenset({'__iter__'})

通過上面的代碼,可以清楚的看出迭代器類型Iterator繼承自可迭代類型Iterable,可迭代Iterable繼承自object基類,迭代器Iterator類型包含__iter()____next()__方法,而可迭代類型Iteratble僅僅包含__iter__()。可迭代對象,通過__iter()__返回一個迭代器對象,迭代器對象的__next()__方法則實際用於被迴圈。

完善自己實現一個迭代器

我們現在再將MyIter類型實現可迭代介面Iterable,即實現__iter__()方法。

>>> class MyIter():

def __init__(self,max_value):
    self.current_value = 0
    self.max_value = max_value

def __iter__(self):
    return self

def __next__(self):
    if self.current_value < self.max_value:
        result = self.current_value
        self.current_value += 1
        return result
    else:
        raise StopIteration

驗證對象是否可以用於for迴圈

>>> my_iter = MyIter(3)
>>> for i in my_iter:
print(i)

0
1
2

驗證對象是否是Iterator實例

>>> from collections import Iterator
>>> isinstance(my_iter,Iterator)
True

總結

  1. 凡是可作用於for語句迴圈的對象都是Iterable可迭代類型。
  2. 凡是可作用於next()函數的對象都是Iterator迭代器類型。
  3. strtuplelistdictset等類型是Iterable可迭代類型,但不是Iterator迭代器;通過Iterable可迭代類型的__iter()__方法可以獲得一個Iterator迭代器對象,從而使得它們可以被for語句迴圈。
  4. Pythonfor迴圈本質上就是通過調用Iterable可迭代對象的__iter()__方法獲得一個Iterator迭代器對象,然後不斷調用Iterator迭代器對象__next()__方法實現的。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 連我自己把float和絕對定位,都稱為脫離文檔流,想想概念又不那麼清晰,於是尋找了W3C資料來理解,才發覺不應該叫文檔流。 資料 英文:https://www.w3.org/TR/CSS22/visuren.html#normal-flow 中文:http://w3help.org/zh-cn/kb ...
  • 先說下選擇Markdown編輯器的原因,我們進行平臺開發,需要很多的操作手冊和API文檔,要在網站中展示出來就需要是HTML格式的文件,但是由於內容很多,不可能全部由技術人員進行文檔的編寫,如果是只有文檔操作經驗的人來做就會出現很麻煩的情況。 最初,我們先用試著用word來寫,再轉換成HTML文件保 ...
  • 目錄: 前言 基礎學習資料與網站介紹 定製我的博文 3.1 我想要的效果 3.2 基礎知識如何實現 3.2.1 一級標題 3.2.2 二級標題 3.2.3 三級標題 3.2.4 目錄 3.2.5 添加小鏈接 3.3 博客園中具體分塊 3.3.1 整體部分 3.3.2 body部分 3.3.3 博文部 ...
  • 今天主管給了我個需求,說要用混合開發,用H5調用本地攝像頭進行掃描二維碼,我之前有做過原生安卓的二維碼掃一掃,主要是通過調用zxing插件進行操作的,其中還弄了個閃光燈.但是純H5的沒接觸過,心裡沒底,於是晚上回家開始網上各處找方案.以下是我對於H5掃描二維碼以及調用本地攝像頭的理解以及代碼.科普網 ...
  • 一場大戲落幕,首屆DDD中國峰會如大會主題色一般的紅。或許在12月9日這一天,全中國的DDD粉絲大約有一半都匯聚在了國家會議中心。聽起來是幸,其實是不幸,因為DDD在中國的人群基數實在是太少了。 因為要負責大會的其中一個Track,期間又要接受採訪,另外還有朋友到訪,所以除了前面的兩個keynote ...
  • 由於某些特定的業務場景,當多個小程式需要一個服務端後臺提供數據時,大家可能想到是HTTP路由。是的,實際上我們使用微服務的GateWay網關也是一樣的,如下圖微服務架構: 網關GateWay的作用在於提供統一的入口來訪問內部的API, 隔離外部訪問與內部系統。集成了非業務性的功能(如安全檢查、頻次限... ...
  • 一:介紹 愛回收是一個和京東回收類似的產品,本質是將用戶不需要的手機,電腦,數位產品等進行回收,我之前使用京東回收過冰箱,感覺京東回收做得蠻好的,通過手機就能搞定一切,然而愛回收我是在兩個月前逛街無意發現的,看到很多年輕人去愛回收提供的設備上搜索商品,它和京東最大的不同是,在查詢回收商品現場,有工作 ...
  • php7從推出到現在,前兩天官方已經發佈到7.2版本,把自己升級和安裝php7中遇到的問題和解決方法做一個筆記,內容主要包括:1) mysql2) php3) nginx4) memcache擴展5) redis擴展 由於內容很長,會分為多篇文章來講述,當然你可能遇到比我更多的問題需要解決,因為我們 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...