今天來講講「迭代器」的內容,其實已經拖了好多天了,感覺再不寫就要忘記了。「迭代」相信對你來說已經不陌生了,我前面曾經專門用一篇文章來講,如果你已經沒有什麼印象的話,就再點進去看看(零基礎學習 python 之初識迭代)。
首先我們先來看一種檢查是否可迭代的方法:
>>> hasattr(list,'__iter__')
true
可以用上面的這種方法檢查已經學習過的其他預設型別的物件,比如字串,列表,字典等是否是可迭代的。
iter() 是乙個特殊方法,它是迭代規則的基礎,有了它,就說明物件是可迭代的。跟迭代有關的乙個內建函式 iter(),這個函式我們在之前的文章中介紹過,它返回的是乙個迭代器物件,比如像下面這樣:
>>> list1 = [1,2,3,4]
>>> iter_list = iter(list1)
>>> iter_list
從上述**的結果可以看出,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 在這的強大之處,我們先來寫乙個迭代器物件:
class myrange:
def __init__(self,n):
self.i = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i <= self.n:
i = self.i
self.i += 1
return i
else:
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)
...1
14
我們在上面重複兩次呼叫列表 list1 進行迴圈,都是能正常進行的,這個列表相當於乙個可以長久使用的東西,可以重複使用。
在 python 中,除了列表解析式以外,還可以做成元組解析式,方法也是非常的簡單:
>>> tuple1 = (x**x for x in range(3))
>>> tuple1
at 0x0000000001df16d8>
>>> for i in tuple1:print(i)
...114
>>> for i in tuple1:print(i)
...
對於 tuple1,我們可以看到它是乙個 generator 物件,關於這個是啥我們先不管,後面我會單獨來說的。當我們把它用到迴圈中的時候,它明顯是個一次性用品,再次使用的時候它就什麼也不顯示了。
>>> type(list1)
>>> type(tuple1)
由上面可以看出,list1 和 tuple1 是兩種不同的物件,它們之間的區別不僅僅是 tuple1 是乙個元組這麼簡單,它還是 generator。其它的我們先不管,你可以嘗試一下在互動模式下輸入 dir(tuple1),檢視它是否有iter和next,我可以先告訴你,是有的。
既然是有的,那麼 tuple1 引用的就是乙個迭代器的物件,它的next() 方法促使它只能向前。
迭代器到這就寫完了,從內容來看迭代器確實有其過人之處,但是它不是萬能的,比如它只能向前,不能回退。還有乙個是迭代器並不適合在多執行緒的環境中對可變集合使用,現在這個東西看起來可能還是有點困難,如果以後有機會寫多執行緒的話,再做解釋。
python之迭代器
可迭代物件就是序列觀念的通用化,如果物件是實際儲存的序列,或者可以在迭代工具環境 eg for迴圈 中一次產生乙個結果的物件,就可看成是可迭代的。可迭代物件包括實際序列和按照需求而計算的虛擬序列。常見的迭代工具 for迴圈 列表解析 in成員關係測試以及map內建函式等。1.檔案迭代器 readli...
Python之迭代器
我們已經知道,可以直接作用於for迴圈的資料型別有以下幾種 一類是集合資料型別,如list tuple dict set str等 一類是generator,包括生成器和帶yield的generator function。這些可以直接作用於for迴圈的物件統稱為可迭代物件 iterable。可以使用...
python之迭代器
首先需要搞清楚兩個概念 可迭代,迭代器,兩者不能混為一談。可以直接作用於for迴圈的物件統稱為可迭代物件 iterable python裡可以用isinstance iterable 來檢測第乙個引數是不是可迭代的 這裡第乙個引數是乙個列表 注意,可迭代和 迭代器 是不一樣的!可以被next 函式呼...