Python 拓展之迭代器

2022-05-30 01:30:13 字數 3330 閱讀 4458

今天來講講「迭代器」的內容,其實已經拖了好多天了,感覺再不寫就要忘記了。「迭代」相信對你來說已經不陌生了,我前面曾經專門用一篇文章來講,如果你已經沒有什麼印象的話,就再點進去看看(零基礎學習 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),檢視它是否有iternext,我可以先告訴你,是有的。

既然是有的,那麼 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 函式呼...