Python基礎-16生成器-迭代器

来源:https://www.cnblogs.com/surpassme/archive/2020/06/01/13028211.html
-Advertisement-
Play Games

16.生成器-迭代器 可迴圈迭代的對象稱為可迭代對象,迭代器和生成器函數是可迭代對象,在Python中提供了定義迭代器和生成器的協議和方法。 16.1 迭代和可迭代對象 16.1.1 可迭代對象、迭代器和可迭代協議 1.可迭代對象 在Python中,實現了__iter__()的對象是可迭代對象(It ...


16.生成器-迭代器

    可迴圈迭代的對象稱為可迭代對象,迭代器和生成器函數是可迭代對象,在Python中提供了定義迭代器和生成器的協議和方法。

16.1 迭代和可迭代對象

16.1.1 可迭代對象、迭代器和可迭代協議

1.可迭代對象

    在Python中,實現了__iter__()的對象是可迭代對象(Iterable)。使用內置函數iter(obj),可以調用可迭代對象obj的__iter__()方法,並返回一個迭代器(iterator)。如字元串、元組、列表等都是可迭代對象,生成器函數和生成器表達式也是可迭代對象。判斷一個對象是否為可迭代對象,可使用以下方式:

>>> from collections import abc
>>> isinstance((1,2,3,4),(abc.Iterable,))
True
>>> isinstance("abcdef",(abc.Iterable,))
True
>>> isinstance(123,(abc.Iterable,))
False
>>> isinstance("123",(abc.Iterable,))
True
>>> isinstance({1,2,3},(abc.Iterable,))
True
>>> isinstance({"a":1,"b":2},(abc.Iterable,))
True

2.迭代器

    實現了__next__的對象是迭代器,可以使用內置函數next(),調用迭代器的__next__()方法,依次返回下一個值,如果沒有值,則拋出異常StopIteration。使用迭代器可以實現對象的迭代迴圈,讓程式更加通用,高效。示例如下所示:

>>> from collections import abc
>>> tempA=(i**2 for i in range(10))
>>> isinstance(tempA,(abc.Iterable,))
True
>>> tempB={i*2 for i in range(10)}
>>> isinstance(tempB,(abc.Iterable,))
True

3.迭代器協議

    迭代器對象必須實現兩個方法__iter__()__next__(),這兩個方法被稱為迭代器協議。__iter__()用於返回對象本身,以方便使用迴圈語句(for)進行迭代,__next__()用於返回下一元素。示例如下所示:

>>> from collections import abc
>>> tempA=(i**2 for i in range(10))
>>> help(tempA)
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __next__(self, /)
 |      Implement next(self).

16.1.2 可迭代對象的迭代:iter和next函數

    使用內置函數iter(iterable),可以返回可迭代對象iterable的迭代器;使用內置函數next()函數,可依次返回迭代器對象的下一個值,如果沒有值,則拋出異常StopIteration。示例如下所示:

>>> temp=[1,2,3,4] # 可迭代對象
>>> v=iter(temp)   # 通過內置函數iter獲取iterator
>>> next(v)        # 通過內置函數next獲取值
1
>>> next(v)
2
>>> next(v)
3
>>> next(v)
4
>>> next(v)       # 當沒有值,則拋出異常StopIteration
Traceback (most recent call last):
  File "<input>", line 1, in <module>
StopIteration

    除了使用next函數個,也可以使用while迴圈可迭代對象,如下所示:

temp=[1,2,3,4]
v=iter(temp)
while True:
    try:
        value=next(v)
    except StopIteration:
        break
    print(value,end=" ")

運行結果如下所示:

1 2 3 4

16.1.3 可迭代對象的迭代:for語句

    實際項目中,通常會使用for語句實現可迭代對象的迭代。Python中的for迴圈實現了自動迭代可迭代對象的功能,如下所示:

>>> temp=[1,2,3,4]
>>> for item in temp:
...     print(item,end=" ")
...     
1 2 3 4 
>>> for item in "abcdef":
...     print(item,end="-")
...     
a-b-c-d-e-f-

16.2 自定義可迭代對象和迭代器

    創建一個類,定義__iter__()和__next__()兩個方法。實例化該類的對象,即為可迭代對象,也是迭代器。示例如下所示:

class Fibonacci:

    def __init__(self):
        self._first=0
        self._second=1

    def __next__(self):
        # f(n)=f(n-1)+f(n-2)
        self._first,self._second=self._second,self._first+self._second
        return self._first
    def __iter__(self):
        return self

fib=Fibonacci()
for f in fib:
    if f<100:
        print(f,end=" ")
    else:
        break

輸出結果如下所示:

1 1 2 3 5 8 13 21 34 55 89

16.3 生成器函數

    在函數定義中,如果使用關鍵字yield語句代替return返回一個值,則表示定義了一個生成器函數(generator)。生成器函數使用yield語句返回一個值,然後保存當前函數的整個執行狀態,等待下一次調用。生成器函數是一個迭代器,是可迭代對象。示例如下所示:

>>> def generatorSample(n):
...     for i in range(n):
...         yield i**2
...         
>>> f=generatorSample(5)
>>> f
<generator object generatorSample at 0x00000260CE70E7C8>
>>> item=iter(f)    # 通過內置函數iter獲得iterator
>>> next(item)      # 通過內置函數next獲取一個值
0
>>> next(item)      # 通過內置函數next獲取一個值
1
>>> for i in f:
...     print(i,end=" ")
...     
4 9 16              # 使用for迴圈獲取剩下的值

    下麵我們再用生成器生成Fibonacci數列,示例代碼如下所示:

def Fibonacci():
    first,second=0,1
    while True:
        first,second=second,first+second
        yield first

for f in Fibonacci():
    if f<100:
        print(f,end=" ")
    else:
        break

輸出結果如下所示:

1 1 2 3 5 8 13 21 34 55 89 

16.4 反向迭代器:reversed迭代器

    使用內置函數reversed(),可以實現一個反向迭代器。如果一個可迭代對象實現了__reversed__()方法,則可使用reversed()函數獲得其反向可迭代對象。示例如下所示:

>>> reversed([1,2,3,4,5])
<list_reverseiterator object at 0x00000260CF0D8908>
>>> for item in reversed([1,2,3,4,5]):
...     print(item,end=" ")
...     
5 4 3 2 1

    實現一個可反向迭代的迭代器示例:

class CountSample:

    def __init__(self,startIndex):
        self._startIndex=startIndex

    # 正向迭代
    def __iter__(self):
        n=self._startIndex
        while n > 0:
            yield n
            n-=1

    # 反向迭代
    def __reversed__(self):
        n=1
        while n<= self._startIndex:
            yield n
            n+=1

if __name__ == '__main__':
    obj=CountSample(10)
    print("正向迭代")
    for item in obj :
        print(item,end=" ")
    print("\n反向迭代")
    for item in reversed(obj):
        print(item,end=" ")

輸出結果如下所示:

正向迭代
10 9 8 7 6 5 4 3 2 1
反向迭代
1 2 3 4 5 6 7 8 9 10

16.5 生成器表達式

    使用生成器表達式,可以簡便快捷返回一個生成器。生成器表達式的語法和前面所講的列表解析式基本一樣,區別在於生成器表達式使用()代表[],基本使用格式如下所示:

( expr for iterVar in iterable )
( expr for iterVar in iterable if condition)

    表達式expr使用每次迭代內容iterVar,計算生成一個列表。如果在指定條件表達式condition,則只有滿足條件的iterable元素參與迭代。如下所示:

>>> (i**2 for i in range(10))
<generator object <genexpr> at 0x00000260CF0B0EC8> # 輸出表明是一個生成器
>>> for item in (i**2 for i in range(10)):
...     print(item,end=" ")
...     
0 1 4 9 16 25 36 49 64 81

>>> for item in (i**2 for i in range(10) if i%2==0):
...     print(item,end=" ")
0 4 16 36 64 

16.5 小結

  • 1.可迭代對象(iterable):可迴圈迭代的對象稱為可迭代對象
  • 2.迭代器(iterator): 實現了__iter__()__next__()的對象,__iter__返回迭代器自身,__next__返回迭代器中的下一個值,如果沒有元素,則拋出StopIteration異常
  • 3.生成器(generator):一種特殊的迭代器,使用關鍵字yield定義,生成器一定是迭代器,反之則不成立。
  • 4.迭代對象與迭代器的示意圖如下所示:

160501迭代對象與迭代器.png

本文地址:https://www.cnblogs.com/surpassme/p/13028211.html
本文同步在微信訂閱號上發佈,如各位小伙伴們喜歡我的文章,也可以關註我的微信訂閱號:woaitest,或掃描下麵的二維碼添加關註:
MyQRCode.jpg


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

-Advertisement-
Play Games
更多相關文章
  • 觀察者模式是一種經常使用的設計模式,在軟體系統中對象並不是孤立存在的,一個對象行為的改變可能會導致其他與之存在依賴關係的對象行為發生改變,觀察者模式用於描述對象之間的依賴關係。 模式動機 很多情況下,對象不是孤立存在的,想象這麼一個場景:你和女朋友去旅行,晚上回到賓館,女朋友穿著厚厚的大衣,從外表看 ...
  • Java生鮮電商平臺-生鮮電商數據分析思維以及指標(小程式/APP) 說明:在生鮮電商行業火爆和轉型的背後,數據分析往往成了主要的助推劑之一,通過對商品、用戶、平臺數據的分析,商家就能知道什麼樣的商品好賣,什麼樣的人愛買,哪一類的促銷活動更受歡迎等等,從而對症下藥調整策略,精準營銷。於是,近年來電商 ...
  • 1、數據類型 go語言支持的基礎類型: 整型:int,int8,int16,int32,int64 無符號整型:uint,uint8,uint16,uint32,uint64 其中預設類型為int,int表示32位或64位與操作系統有關 位元組:byte 布爾:bool 浮點型:float32,flo ...
  • Java中內置類及其方法的使用通常翻閱對應的API文檔即可,但是對於常用的一些類和方法還是需要我們能夠熟練的使用。 一、System System.gc():手動啟動垃圾回收器,垃圾回收器通常是自動啟動的,某些時候Java可能覺得當下的情況並不需要啟動gc,但是你又想啟動的話,就可以調用這個方法手動 ...
  • python2 預設的編碼方式是ASCII碼 在文件的首行:#-- encoding:utf-8 -- python3 預設編碼方式utf-8 0、列印內容 print () print('Hellow World !') 1、變數 變數:就是將一些運算的中間結果暫存到記憶體中,以便後續代碼調用。 必 ...
  • *6.38(生成隨機字元)使用程式清單6-10RandomCharacter中的方法,列印100個大寫字母及100個一位數字,每行列印10個。 *6.38(Generate random characters) Use the methods in RandomCharacter in Listin ...
  • pydbclib是一個通用的python關係型資料庫操作工具包,使用統一的介面操作各種關係型資料庫(如 oracle、mysql、postgres、hive、impala等)進行增刪改查,它是對各個python資料庫連接驅動包(如sqlalchemy、pymysql、cx_Oracle、pyhive ...
  • 17.對象引用和拷貝 我們先來看看以下向個概念 變數:是系統變數名錶中的元素,通常是由程式員進行定義聲明 對象:是電腦分配的一塊記憶體,需要足夠的空間去表示它的值 引用:是自動形成的從變數到對象的指針 可變對象:允許對自身內容進行修改。如list、dict、set、自定義類型等。 不可變對象:不允許 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...