日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

[转载] 【python魔术方法】迭代器(__iter__和__next__)

發(fā)布時間:2025/3/11 python 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] 【python魔术方法】迭代器(__iter__和__next__) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

參考鏈接: Python __iter __()和__next __()| 將對象轉(zhuǎn)換為迭代器

文章目錄

?`__iter__` 和 `__next__`真正的迭代器總結(jié)

?

?

?

python里面有很多的以__開始和結(jié)尾的函數(shù),利用它們可以完成很多復(fù)雜的邏輯代碼,而且提高了代碼的簡潔性,本文主要總結(jié)了迭代器用到的魔術(shù)方法,并且主要以代碼例子進(jìn)行解釋。?

__iter__ 和 __next__?

其實(shí)這里需要引入一個概念,叫迭代器,常見的就是我們在使用for語句的時候,python內(nèi)部其實(shí)是把for后面的對象上使用了內(nèi)建函數(shù)iter,比如:?

a = [1, 2, 3]

for i in a:

? ? do_something()

?

其實(shí)在python內(nèi)部進(jìn)行了類似如下的轉(zhuǎn)換:?

a = [1, 2, 3]

for i in iter(a):

? ? do_something()

?

那么iter返回的是什么呢,就是一個迭代對象,它主要映射到了類里面的__iter__函數(shù),此函數(shù)返回的是一個實(shí)現(xiàn)了__next__的對象。注意理解這句話,比如:?

class B(object):

? ? def __next__(self):

? ? ? ? raise StopIteration

?

class A(object):

? ? def __iter__(self):

? ? ? ? return B()

?

我們可以看見,A這個類實(shí)現(xiàn)了一個__iter__函數(shù),返回的是B()的實(shí)例對象,其中B里面實(shí)現(xiàn)了__next__這個函數(shù)。?

下面引入幾個概念: Iterable: 有迭代能力的對象,一個類,實(shí)現(xiàn)了__iter__,那么就認(rèn)為它有迭代能力,通常此函數(shù)必須返回一個實(shí)現(xiàn)了__next__的對象,如果自己實(shí)現(xiàn)了,你可以返回self,當(dāng)然這個返回值不是必須的; Iterator: 迭代器(當(dāng)然也是Iterable),同時實(shí)現(xiàn)了__iter__和__next__的對象,缺少任何一個都不算是Iterator,比如上面例子中,A()可以是一個Iterable,但是A()和B()都不能算是和Iterator,因?yàn)锳只實(shí)現(xiàn)了__iter__,而B只實(shí)現(xiàn)了__next__()。?

我們可以使用collections里面的類型來進(jìn)行驗(yàn)證:?

class B(object):

? ? def __next__(self):

? ? ? ? raise StopIteration

?

class A(object):

? ? def __iter__(self):

? ? ? ? return B()

?

?

from collections.abc import *

?

a = A()

b = B()

print(isinstance(a, Iterable))

print(isinstance(a, Iterator))

?

print(isinstance(b, Iterable))

print(isinstance(b, Iterator))

?

結(jié)果是:?

True

False

False

False

?

讓我們稍微對B這個類做一點(diǎn)修改:?

class B(object):

? ? def __next__(self):

? ? ? ? raise StopIteration

?

? ? def __iter__(self):

? ? ? ? return None

?

class A(object):

? ? def __iter__(self):

? ? ? ? return B()

?

?

from collections.abc import *

?

a = A()

b = B()

print(isinstance(a, Iterable))

print(isinstance(a, Iterator))

?

print(isinstance(b, Iterable))

print(isinstance(b, Iterator))

?

結(jié)果是:?

True

False

True

True

?

真正的迭代器?

上面只是做了幾個演示,這里具體說明一下: 當(dāng)調(diào)用iter函數(shù)的時候,生成了一個迭代對象,要求__iter__必須返回一個實(shí)現(xiàn)了__next__的對象,我們就可以通過next函數(shù)訪問這個對象的下一個元素了,并且在你不想繼續(xù)有迭代的情況下拋出一個StopIteration的異常(for語句會捕獲這個異常,并且自動結(jié)束for),下面實(shí)現(xiàn)了一個自己的類似range函數(shù)的功能。?

class MyRange(object):

? ? def __init__(self, end):

? ? ? ? self.start = 0

? ? ? ? self.end = end

?

? ? def __iter__(self):

? ? ? ? return self

?

? ? def __next__(self):

? ? ? ? if self.start < self.end:

? ? ? ? ? ? ret = self.start

? ? ? ? ? ? self.start += 1

? ? ? ? ? ? return ret

? ? ? ? else:

? ? ? ? ? ? raise StopIteration

?

from collections.abc import *

?

a = MyRange(5)

print(isinstance(a, Iterable))

print(isinstance(a, Iterator))

?

for i in a:

? ? print(i)

?

結(jié)果是:?

True

True

0

1

2

3

4

?

接下來我們使用next函數(shù)模擬一次:?

class MyRange(object):

? ? def __init__(self, end):

? ? ? ? self.start = 0

? ? ? ? self.end = end

?

? ? def __iter__(self):

? ? ? ? return self

?

? ? def __next__(self):

? ? ? ? if self.start < self.end:

? ? ? ? ? ? ret = self.start

? ? ? ? ? ? self.start += 1

? ? ? ? ? ? return ret

? ? ? ? else:

? ? ? ? ? ? raise StopIteration

?

a = MyRange(5)

print(next(a))

print(next(a))

print(next(a))

print(next(a))

print(next(a))

print(next(a)) # 其實(shí)到這里已經(jīng)完成了,我們在運(yùn)行一次查看異常

?

可以看見一個很明顯的好處是,每次產(chǎn)生的數(shù)據(jù),是產(chǎn)生一個用一個,什么意思呢,比如我要遍歷[0, 1, 2, 3.....]一直到10億,如果使用列表的方式,那么是會全部載入內(nèi)存的,但是如果使用迭代器,可以看見,當(dāng)用到了(也就是在調(diào)用了next)才會產(chǎn)生對應(yīng)的數(shù)字,這樣就可以節(jié)約內(nèi)存了,這是一種懶惰的加載方式。?

總結(jié)?

可以使用collection.abs里面的Iterator和Iterable配合isinstance函數(shù)來判斷一個對象是否是可迭代的,是否是迭代器對象iter實(shí)際是映射到了__iter__函數(shù)只要實(shí)現(xiàn)了__iter__的對象就是可迭代對象(Iterable),正常情況下,應(yīng)該返回一個實(shí)現(xiàn)了__next__的對象(雖然這個要求不強(qiáng)制),如果自己實(shí)現(xiàn)了__next__,當(dāng)然也可以返回自己同時實(shí)現(xiàn)了__iter__和__next__的是迭代器(Iterator),當(dāng)然也是一個可迭代對象了,其中__next__應(yīng)該在迭代完成后,拋出一個StopIteration異常for語句會自動處理這個StopIteration異常以便結(jié)束for循環(huán)?

生成器相關(guān)的文檔已經(jīng)在這里。

總結(jié)

以上是生活随笔為你收集整理的[转载] 【python魔术方法】迭代器(__iter__和__next__)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。