python迭代器详解
一、什么是迭代器
迭代是python中訪問集合元素的一種非常強大的一種方式。迭代器是一個可以記住遍歷位置的對象,因此不會像列表那樣一次性全部生成,而是可以等到用的時候才生成,因此節省了大量的內存資源。迭代器對象從集合中的第一個元素開始訪問,直到所有的元素被訪問完。迭代器有兩個方法:iter()和next()方法。
二、可迭代的對象
類似于list、tuple、str 等類型的數據可以使用for …… in…… 的循環遍歷語法從其中依次拿到數據并進行使用,我們把這個過程稱為遍歷,也稱迭代。python中可迭代的對象有list(列表)、tuple(元組)、dirt(字典)、str(字符串)set等。
?
?
除此之外,也可以創建一個可迭代的對象:只要此對象含有__iter__方法,那么它就是一個可迭代的對象,如下面的例子:其中定義了一個__iter__方法,我們通過isinstance()函數以及Iterable來判斷由Classmate類創建的class1對象是否是可迭代的對象:若class1是一個Iterable(可迭代對象)則結果返回為True;否則,結果為False。
運行結果如下:
三、創建一個迭代器
1.一個類(對象)只要含有“__iter__”、"__next__"兩個方法,就將其稱為迭代器。__iter__方法返回一個特殊的迭代器對象,而這個迭代器對象自動實現了_next__方法,并返回一個值,最后通過拋出異常StopIteration來結束迭代。我們來給上一個例子增加__next__方法:
還是通過isinstance()函數來判斷,如果class1是一個迭代器(Iterator),則結果返回True;否則返回False。運行結果如下:
2.只是名義上的 可迭代對象/迭代器 還不夠,具有相應的功能才算是完整。首先,對于__iter__方法,它需要具有一個可以返回一個迭代器對象的功能(這個對象可以是自己(前提是本身就是一個迭代器),也可以是其它迭代器);對于__next__方法,它需要標記并返回下一個迭代器對象。代碼如下(為防止迭代速度過快,我們添加sleep來控制速度):
from collections import Iterable from collections import Iterator import timeclass Classmate(object):"""定義一個同學類"""def __init__(self):self.name = list()self.name_num = 0def add(self,name):self.name.append(name)def __iter__(self):return self ? # 返回本身def __next__(self):# 記憶性返回數據if self.name_num < len(self.name):ret = self.name[self.name_num]self.name_num += 1return retclass1 = ?Classmate() class1.add("張三") class1.add("李四") class1.add("王五")print("判斷是否是可迭代的對象:", isinstance(class1,Iterable))print("判斷是否是迭代器:", isinstance(class1,Iterator))for name in class1:print(name)time.sleep(1)
運行結果如下:
可以發現,當需要讀取的內容讀取完之后不會停止,而是無限循環的繼續返回空值。因此我們可以為其添加拋出異常(StopIteration,python中用于標標識迭代完成,防止出現無限循環的情況)的程序,當需要的數據讀取完成時就拋出異常,從而結束:
from collections import Iterable from collections import Iterator import timeclass Classmate(object):"""定義一個同學類"""def __init__(self):self.name = list()self.name_num = 0def add(self,name):self.name.append(name)def __iter__(self):return self ? # 返回本身def __next__(self):if self.name_num < len(self.name):ret = self.name[self.name_num]self.name_num += 1return ret# 拋出異常,當循環后自動結束else:raise StopIterationclass1 = ?Classmate() class1.add("張三") class1.add("李四") class1.add("王五")print("判斷是否是可迭代的對象:", isinstance(class1,Iterable))print("判斷是否是迭代器:", isinstance(class1,Iterator))for name in class1:print(name)time.sleep(1)
運行結果如下:
四、迭代器的應用
迭代器最核心的功能就是可以通過__next__方法的調用來返回下一個值。而這個值不是從已有的數據中讀取的,而是通過程序按照一定的規則生成的。這也就意味著我們可以不再依賴一個現存的數據集合來存放數據,而是邊用邊生成,這樣的好處就是可以節省大量的內存空間。我們通過對比以下問題的兩個解決方法,來進一的理解其應用優勢:
問題:試編寫一個程序實現斐波那契數列(0,1,1,2,3,5,8,13,21……后一項總是等于前兩項的和):
方法一:
a = 0 b = 1 myFibonacci = list()nums = int(input("請輸入需要生成Fibonacci數列項的個數:"))i = 0 while i < nums:myFabonacci.append(a)a,b = b,a+bi += 1for num in myFibonacci:print(num)
方法二:
假如我們需要生成10個Fibonacci數列的項,兩者的運行結果相同,如下:
雖然結果相同,但實際效果卻相差巨大。來看一下方法一,他是通過while循環立即生成一個列表用來存放數據,接著再從已有的數據中讀取所需數據,而這需要占用一定的內存空間;再來看一下方法二,它并沒有用到列表,而是返回一個迭代器,在需要的時候生成相關數據。縱觀以上兩種方法,在生成個數較小時,兩者相差不大,但當生成個數是10萬,100萬,1000萬呢?前者需要消耗大量的內存資源,而后者僅需占用一點內存即可。這也是python2中range()函數和python3中range()函數的不同點,python3的range()函數采用了迭代器的方式,不再依賴于現有的數據集合,也就相當于python2中的xrange()函數。
五、小結:
1.可迭代對象不一定是迭代器。
2.迭代器一定是可迭代對象。
3.容器類型(list tuple dict str set )是可迭代對象但不是迭代器。
?
————————————————
版權聲明:本文為CSDN博主「xcy.小相」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_45807032/article/details/105219674
總結
以上是生活随笔為你收集整理的python迭代器详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP如何下载微信语音到服务器,并将am
- 下一篇: Python——Numpy 之数组拼接