Python 拓展之迭代器

2020-12-15 Python空間

本文字數:2465 字

閱讀本文大概需要:7 分鐘

寫在之前

今天來講講「迭代器」的內容,其實已經拖了好多天了,感覺再不寫就要忘記了。「迭代」相信對你來說已經不陌生了,我前面曾經專門用一篇文章來講,如果你已經沒有什麼印象的話,就再點進去看看(零基礎學習 Python 之初識迭代)。

迭代器

首先我們先來看一種檢查是否可迭代的方法:

>>> hasattr(list,'__iter__')True

可以用上面的這種方法檢查已經學習過的其他默認類型的對象,比如字符串,列表,字典等是否是可迭代的。

__iter__() 是一個特殊方法,它是迭代規則的基礎,有了它,就說明對象是可迭代的。跟迭代有關的一個內建函數 iter(),這個函數我們在之前的文章中介紹過,它返回的是一個迭代器對象,比如像下面這樣:

>>> list1 = [1,2,3,4]>>> iter_list = iter(list1)>>> iter_list<list_iterator object at 0x00000000021CE438>

從上述代碼的結果可以看出,iter_list 引用的是迭代器對象。那麼在這裡有一個問題,iter_list 和 list1 有區別嗎?我們來試一下:

>>> hasattr(list1,'__iter__')True>>> hasattr(iter_list,'__iter__')True

從上面看出它們都有 __iter__,說明它們都是可迭代的。

>>> hasattr(list1,"__next__")False>>> hasattr(iter_list,"__next__")True

我們把像 iter_list 所引用的對象那樣,稱之為「迭代器對象」。顯而易見的是,迭代器對象必然是可迭代的,反正則不一定。且 Python 中迭代器對象實現的是 __next__() 方法。

為了體現一下 Python 在這的強大之處,我們先來寫一個迭代器對象:

classMyRange:def__init__(self,n):self.i = 1self.n = ndef__iter__(self):returnselfdef__next__(self):ifself.i <= self.n: i = self.iself.i += 1return ielse: raise StopIteration()if __name__ == "__main__": x = MyRange(5) print([i for i in x])

上述代碼的運行結果如下所示:

[1,2,3,4,5]

上述的代碼仿寫了類似 range() 的類,但是與 range() 又有所不同,除了結果不同以外還包括以下 2 點:

1.__iter__() 是類中的核心,它返回了迭代器的本身,一個實現了 __iter__() 方法的對象,就意味著它是可迭代的。

2.實現了 __next__() 方法,從而使得這個對象是迭代器對象。

接下來我們來看看 range() 本身:

>>> a = range(5)>>> hasattr(a,'__iter__')True>>> hasattr(a,'__next__')False>>> print(a)range(0, 5)

由上面我們就可以看出,其實我們所寫的類和 range() 本身還是有很大區別的。

通過上面的內容和我們之前的文章對迭代的講述,下面我們對迭代器做一個概括:

1.在 Python 中,迭代器是遵循迭代協議的對象。我們可以使用 iter() 從任何序列得到迭代器(exp: list,turple,set and so on)。

2.當自己編寫迭代器的類的時候,其中實現 __iter__() 和 __next__() 方法,如果沒有元素的話,會引發 StopIteration 異常。

3.如果有很多值的話,列表會佔用太多的內存,而迭代器則佔用的更少,它從第一個元素開始訪問,直到所有的元素被訪問完結束,只能向前衝,不能後退。

迭代器不僅僅是實用而已,而且也非常的有趣,讓我們來看下面的操作:

>>> list1 = [x**x for x in range(3)]>>> list1[1, 1, 4]>>> for i in list1:print(i)...114>>> for i in list1:print(i)...114

我們在上面重複兩次調用列表 list1 進行循環,都是能正常進行的,這個列表相當於一個可以長久使用的東西,可以重複使用。

在 Python 中,除了列表解析式以外,還可以做成元組解析式,方法也是非常的簡單:

>>> tuple1 = (x**x for x in range(3))>>> tuple1<generator object <genexpr> at 0x0000000001DF16D8>>>> for i in tuple1:print(i)...114>>> for i in tuple1:print(i)...

對於 tuple1,我們可以看到它是一個 generator 對象,關於這個是啥我們先不管,後面我會單獨來說的。當我們把它用到循環中的時候,它明顯是個一次性用品,再次使用的時候它就什麼也不顯示了。

>>> type(list1)<class 'list'>>>> type(tuple1)<class 'generator'>

由上面可以看出,list1 和 tuple1 是兩種不同的對象,它們之間的區別不僅僅是 tuple1 是一個元組這麼簡單,它還是 generator。其它的我們先不管,你可以嘗試一下在交互模式下輸入 dir(tuple1),查看它是否有 __iter__ 和 __next__,我可以先告訴你,是有的。

既然是有的,那麼 tuple1 引用的就是一個迭代器的對象,它的 __next__() 方法促使它只能向前。

寫在之後

迭代器到這就寫完了,從內容來看迭代器確實有其過人之處,但是它不是萬能的,比如它只能向前,不能回退。還有一個是迭代器並不適合在多線程的環境中對可變集合使用,現在這個東西看起來可能還是有點困難,如果以後有機會寫多線程的話,再做解釋。

如果你覺得本篇文章對你有幫助的話,歡迎點讚轉發,讓更多的人可以看到,歡迎大家聯繫我。

The end。

相關焦點

  • 面試題-python 什麼是迭代器?
    前言python 裡面有 3 大神器:迭代器,生成器,裝飾器。
  • 一文搞懂Python迭代器和生成器
    很多童鞋搞不懂python迭代器和生成器到底是什麼?它們之間又有什麼樣的關係?
  • 傳智播客鄭州校區Python學習之迭代器與生成器
    三、傳智播客Python學習:迭代器迭代器和遞歸函數的區別:遞歸函數是不斷的重複調用自己,必須有一個明確的條件,而且每進行更深一層的循環,規模一定要較之前要小,迭代器,每次循環都要依賴於上一次的結果。
  • 【Python基礎】可迭代對象&迭代器對象及其實現
    首選確保for循環的in後面是一個可迭代對象,這樣就能通過python內置函數iter()得到一個迭代器對象(iterator)我們再看看迭代的籤名, 要麼傳入的參數(對象)本身有迭代器,要麼是一個序列。 我們這裡list__test本身就有迭代器,而str_test是有__getItem__這種序列的接口。
  • python中的yield和return—迭代器和生成器
    文章目錄很多人學習python,不知道從何學起。很多人學習python,掌握了基本語法過後,不知道在哪裡尋找案例上手。
  • 什麼是Python的迭代器和生成器?(附代碼)
    utm_source=blog&utm_medium=python-iterators-and-generators這是我們要介紹的內容:什麼是可迭代對象?什麼是Python迭代器?在Python中創建一個迭代器熟悉Python中的生成器實現Python中的生成器表達式為什麼你應該使用迭代器?
  • Python 迭代器和 C++ 迭代器,最大的不同竟然是……
    當我初學 Python 的時候,我將迭代器理解為一種能夠放在「for xxx in …」的「…」位置的東西;後來隨著學習的深入,我了解到迭代器就是一種實現了迭代器協議的對象;學習 C++ 時,我了解到迭代器是一種行為和指針類似的對象…事實上,迭代器是一個伴隨著迭代器模式(Iterator Pattern)而生的抽象概念,其目的是分離並統一不同的數據結構訪問其中數據的方式
  • Python從小白進階到大神的三大利器之迭代器
    可以看出,Python將list裡面的數據給列印出來,像這樣通過for循環遍歷列表元素的過程就叫做迭代,在Python裡面由於for語句的強大之處,迭代器更多的是用在迭代和遍歷上。那麼什麼是迭代呢?實際上,在Python中,迭代器已經被弱化了,很少有機會自己定義一個迭代器,在進行迭代,因為我們的for在配合可遍歷的對象可以完成我們大部分工作,但是由於迭代器作為Python的從小白到大神的三大利器之一,今天我們就來看看Python的迭代器是怎麼實現的?
  • Python中迭代器和生成器的區別?
    廢話不多說,開始今天的題目:問:說說Python中迭代器和生成器的區別?答:Python中生成器能做到迭代器能做的所有事,而且因為自動創建了__iter__()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表達式取代列表解析,同時節省內存。
  • 雲計算開發學習筆記:Python3迭代器與生成器
    迭代器是一個可以記住遍歷的位置的對象。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。迭代器有兩個基本的方法:iter() 和 next()。字符串,列表或元組對象都可用於創建迭代器:迭代器對象可以使用常規for語句進行遍歷:執行以上程序,輸出結果如下:也可以使用 next() 函數:執行以上程序,輸出結果如下:
  • ES6的生成器和迭代器
    其中兩個特性,生成器和迭代器,極大地改變了我們在更複雜的前端代碼中編寫特定函數的方式。雖然他們之間的關係很好,但他們實際上做的事情可能有點令人困惑,所以讓我們來看看他們。迭代器迭代在編程中是一種常見的做法,通常用於循環一組值,要麼轉換每個值,要麼使用或以某種方式保存它。
  • Python小白教程:生成器 (generator) 和迭代器 (iterator)
    那生成器可不可以叫做迭代器?可以的!至於迭代器是第 2 節的內容。我們知道 for 循環就是遍歷一個迭代器裡的每個元素的,那試試用 for 循環來遍歷生成器 my_nums。nums = [1, 2, 3]for num in nums: print(num)但是 nums 不是迭代器 (只是 for 循環在遍歷前將其轉換成迭代器了),用 next() 會不錯,錯誤信息是「列表對象不是迭代器」。
  • 好程式設計師Python教程分享常見的Python面試題
    1、大數據的文件讀取 利用生成器generator 迭代器進行迭代遍歷:forlineinfile> 2、迭代器和生成器的區別 1)迭代器是一個更抽象的概念,任何對象,如果它的類有next方法和iter方法返回自己本身。
  • python教程:3個非常有用的內置函數
    *版本中是直接返回list的,但在python3.*中是返回一個迭代器 2、map 語法:map(function,*iterable) 解釋:把迭代器(或多個迭代器)通過function函數得到結果 用法:可以設置一個或多個迭代器,然後把相同位置(如果為多個迭代器)的元素通過function函數得到最終結果
  • Python生成器next方法和send方法區別詳解
    住址"python 生成器和迭代器的原理解析一.生成器簡介 在python中,生成器是根據某種算法邊循環邊計算的一種機制.主要就是用於操作大量數據的時候,一般我們會將操作的數據讀入內存中處理,可以計算機的內存是比較寶貴的資源,我認為的當要處理的數據超過內存四分之一的大小時就應該使用生成器. 二.生成器有什麼特點?
  • Python數據讀取之生成器(generator)
    Python生成器是創建迭代器的簡單方法。簡單來說,生成器是一個函數,它返回一個我們可以迭代的對象(迭代器),迭代器一次返回一個值較使用列表將所有數據都加載到內存中,生成器節省了大量內存空間。深度學習的數據讀取部分一般都需要使用迭代器。
  • Python中可迭代對象、迭代器以及iter函數的兩個用法詳解
    這些數據結構之所以能稱之為Iterable,是因為其內部實現了__iter__()方法,從而可迭代。當我們使用for循環時,解釋器會調用內置的iter()函數,調用前首先會檢查對象是否實現了__iter__()方法,如果有就調用它獲取一個迭代器(接下來會講)。加入沒有__iter__()方法,但是實現了__getitem__()方法,解釋器會創建一個迭代器並且按順序獲取元素。如果這兩個方法都沒有找到,就會拋出TypeError異常。
  • python他律筆記系列二
    語法if語句  if-elif-else 與c/c++ 不同的是每個條件後面需要使用冒號:另外python中無switch-case語句while語句 與c/c++一致所需要注意的就是需要加上冒號:另外python中無do...while循環對於 while 1這類死循環可以通過crtl+c強制退出但是有while...else 語句for語句
  • C++(STL):17---deque之迭代器使用
    ,通過調用這些函數,可以獲得表示不同含義的隨機訪問迭代器。cend()和 end() 功能相同,只不過其返回的迭代器類型為常量正向迭代器,不能用於修改元素。crbegin()和 rbegin() 功能相同,只不過其返回的迭代器類型為常量反向迭代器,不能用於修改元素。crend()和 rend() 功能相同,只不過其返回的迭代器類型為常量反向迭代器,不能用於修改元素。
  • 精讀《設計模式 - Iterator 迭代器模式》
    在 generator 的場景中,迭代器不僅用來遍歷聚合,還用於執行代碼。實際上,深究 generator 內部的存儲結構也沒有意義,如果我們不用迭代器進行遍歷,那麼對於複雜結構的遍歷成本是非常高的。結構圖Aggregate: 聚合,需要定義創建迭代器的接口。比如前端規範的 [Symbol.iterator](),或者這裡定義的 CreateIterator()。Iterator: 迭代器,定義了訪問與遍歷的 API。