詳解Python之可迭代對(duì)象,迭代器和生成器
一、概念描述
可迭代對(duì)象就是可以迭代的對(duì)象,我們可以通過(guò)內(nèi)置的iter函數(shù)獲取其迭代器,可迭代對(duì)象內(nèi)部需要實(shí)現(xiàn)__iter__函數(shù)來(lái)返回其關(guān)聯(lián)的迭代器;
迭代器是負(fù)責(zé)具體數(shù)據(jù)的逐個(gè)遍歷的,其通過(guò)實(shí)現(xiàn)__next__函數(shù)得以逐個(gè)的訪問(wèn)關(guān)聯(lián)的數(shù)據(jù)元素;同時(shí)通過(guò)實(shí)現(xiàn)__iter__來(lái)實(shí)現(xiàn)對(duì)可迭代對(duì)象的兼容;
生成器是一種迭代器模式,其實(shí)現(xiàn)了數(shù)據(jù)的惰性生成,即只有使用的時(shí)候才會(huì)生成對(duì)應(yīng)的元素;

二、序列的可迭代性
python內(nèi)置的序列可以通過(guò)for進(jìn)行迭代,解釋器會(huì)調(diào)用iter函數(shù)獲取序列的迭代器,由于iter函數(shù)兼容序列實(shí)現(xiàn)的__getitem__,會(huì)自動(dòng)創(chuàng)建一個(gè)迭代器;
迭代器的
import re
from dis import dis
class WordAnalyzer:
reg_word = re.compile('\w+')
def __init__(self, text):
self.words = self.__class__.reg_word.findall(text)
def __getitem__(self, index):
return self.words[index]
def iter_word_analyzer():
wa = WordAnalyzer('this is mango word analyzer')
print('start for wa')
for w in wa:
print(w)
print('start while wa_iter')
wa_iter = iter(wa)
while True:
try:
print(next(wa_iter))
except StopIteration as e:
break;
iter_word_analyzer()
dis(iter_word_analyzer)
# start for wa
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# this
# is
# mango
# word
# analyzer
# 15 0 LOAD_GLOBAL 0 (WordAnalyzer)
# 2 LOAD_CONST 1 ('this is mango word analyzer')
# 4 CALL_FUNCTION 1
# 6 STORE_FAST 0 (wa)
#
# 16 8 LOAD_GLOBAL 1 (print)
# 10 LOAD_CONST 2 ('start for wa')
# 12 CALL_FUNCTION 1
# 14 POP_TOP
#
# 17 16 LOAD_FAST 0 (wa)
# 18 GET_ITER
# >> 20 FOR_ITER 12 (to 34)
# 22 STORE_FAST 1 (w)
#
# 18 24 LOAD_GLOBAL 1 (print)
# 26 LOAD_FAST 1 (w)
# 28 CALL_FUNCTION 1
# 30 POP_TOP
# 32 JUMP_ABSOLUTE 20
#
# 20 >> 34 LOAD_GLOBAL 1 (print)
# 36 LOAD_CONST 3 ('start while wa_iter')
# 38 CALL_FUNCTION 1
# 40 POP_TOP
#
# 21 42 LOAD_GLOBAL 2 (iter)
# 44 LOAD_FAST 0 (wa)
# 46 CALL_FUNCTION 1
# 48 STORE_FAST 2 (wa_iter)
#
# 23 >> 50 SETUP_FINALLY 16 (to 68)
#
# 24 52 LOAD_GLOBAL 1 (print)
# 54 LOAD_GLOBAL 3 (next)
# 56 LOAD_FAST 2 (wa_iter)
# 58 CALL_FUNCTION 1
# 60 CALL_FUNCTION 1
# 62 POP_TOP
# 64 POP_BLOCK
# 66 JUMP_ABSOLUTE 50
#
# 25 >> 68 DUP_TOP
# 70 LOAD_GLOBAL 4 (StopIteration)
# 72 JUMP_IF_NOT_EXC_MATCH 114
# 74 POP_TOP
# 76 STORE_FAST 3 (e)
# 78 POP_TOP
# 80 SETUP_FINALLY 24 (to 106)
#
# 26 82 POP_BLOCK
# 84 POP_EXCEPT
# 86 LOAD_CONST 0 (None)
# 88 STORE_FAST 3 (e)
# 90 DELETE_FAST 3 (e)
# 92 JUMP_ABSOLUTE 118
# 94 POP_BLOCK
# 96 POP_EXCEPT
# 98 LOAD_CONST 0 (None)
# 100 STORE_FAST 3 (e)
# 102 DELETE_FAST 3 (e)
# 104 JUMP_ABSOLUTE 50
# >> 106 LOAD_CONST 0 (None)
# 108 STORE_FAST 3 (e)
# 110 DELETE_FAST 3 (e)
# 112 RERAISE
# >> 114 RERAISE
# 116 JUMP_ABSOLUTE 50
# >> 118 LOAD_CONST 0 (None)
# 120 RETURN_VALUE
三、經(jīng)典的迭代器模式
標(biāo)準(zhǔn)的迭代器需要實(shí)現(xiàn)兩個(gè)接口方法,一個(gè)可以獲取下一個(gè)元素的__next__方法和直接返回self的__iter__方法;
迭代器迭代完所有的元素的時(shí)候會(huì)拋出StopIteration異常,但是python內(nèi)置的for、列表推到、元組拆包等會(huì)自動(dòng)處理這個(gè)異常;
實(shí)現(xiàn)__iter__主要為了方便使用迭代器,這樣就可以最大限度的方便使用迭代器;
迭代器只能迭代一次,如果需要再次迭代就需要再次調(diào)用iter方法獲取新的迭代器,這就要求每個(gè)迭代器維護(hù)自己的內(nèi)部狀態(tài),即一個(gè)對(duì)象不能既是可迭代對(duì)象同時(shí)也是迭代器;
從經(jīng)典的面向?qū)ο笤O(shè)計(jì)模式來(lái)看,可迭代對(duì)象可以隨時(shí)生成自己關(guān)聯(lián)的迭代器,而迭代器負(fù)責(zé)具體的元素的迭代處理;
import re
from dis import dis
class WordAnalyzer:
reg_word = re.compile('\w+')
def __init__(self, text):
self.words = self.__class__.reg_word.findall(text)
def __iter__(self):
return WordAnalyzerIterator(self.words)
class WordAnalyzerIterator:
def __init__(self, words):
self.words = words
self.index = 0
def __iter__(self):
return self;
def __next__(self):
try:
word = self.words[self.index]
except IndexError:
raise StopIteration()
self.index +=1
return word
def iter_word_analyzer():
wa = WordAnalyzer('this is mango word analyzer')
print('start for wa')
for w in wa:
print(w)
print('start while wa_iter')
wa_iter = iter(wa)
while True:
try:
print(next(wa_iter))
except StopIteration as e:
break;
iter_word_analyzer()
# start for wa
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# this
# is
# mango
# word
# analyzer
四、生成器也是迭代器
生成器是調(diào)用生成器函數(shù)生成的,生成器函數(shù)是含有yield的工廠函數(shù);
生成器本身就是迭代器,其支持使用next函數(shù)遍歷生成器,同時(shí)遍歷完也會(huì)拋出StopIteration異常;
生成器執(zhí)行的時(shí)候會(huì)在yield語(yǔ)句的地方暫停,并返回yield右邊的表達(dá)式的值;
def gen_func():
print('first yield')
yield 'first'
print('second yield')
yield 'second'
print(gen_func)
g = gen_func()
print(g)
for val in g:
print(val)
g = gen_func()
print(next(g))
print(next(g))
print(next(g))
# <function gen_func at 0x7f1198175040>
# <generator object gen_func at 0x7f1197fb6cf0>
# first yield
# first
# second yield
# second
# first yield
# first
# second yield
# second
# StopIteration
我們可以將__iter__作為生成器函數(shù)
import re
from dis import dis
class WordAnalyzer:
reg_word = re.compile('\w+')
def __init__(self, text):
self.words = self.__class__.reg_word.findall(text)
def __iter__(self):
for word in self.words:
yield word
def iter_word_analyzer():
wa = WordAnalyzer('this is mango word analyzer')
print('start for wa')
for w in wa:
print(w)
print('start while wa_iter')
wa_iter = iter(wa)
while True:
try:
print(next(wa_iter))
except StopIteration as e:
break;
iter_word_analyzer()
# start for wa
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# this
# is
# mango
# word
# analyzer
五、實(shí)現(xiàn)惰性迭代器
迭代器的一大亮點(diǎn)就是通過(guò)__next__來(lái)實(shí)現(xiàn)逐個(gè)元素的遍歷,這個(gè)大數(shù)據(jù)容器的遍歷帶來(lái)了可能性;
我們以前的實(shí)現(xiàn)在初始化的時(shí)候,直接調(diào)用re.findall得到了所有的序列元素,并不是一個(gè)很好的實(shí)現(xiàn);我們可以通過(guò)re.finditer來(lái)在遍歷的時(shí)候得到數(shù)據(jù);
import re
from dis import dis
class WordAnalyzer:
reg_word = re.compile('\w+')
def __init__(self, text):
# self.words = self.__class__.reg_word.findall(text)
self.text = text
def __iter__(self):
g = self.__class__.reg_word.finditer(self.text)
print(g)
for match in g:
yield match.group()
def iter_word_analyzer():
wa = WordAnalyzer('this is mango word analyzer')
print('start for wa')
for w in wa:
print(w)
print('start while wa_iter')
wa_iter = iter(wa)
wa_iter1= iter(wa)
while True:
try:
print(next(wa_iter))
except StopIteration as e:
break;
iter_word_analyzer()
# start for wa
# <callable_iterator object at 0x7feed103e040>
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# <callable_iterator object at 0x7feed103e040>
# this
# is
# mango
# word
# analyzer
六、使用生成器表達(dá)式簡(jiǎn)化惰性迭代器
生成器表達(dá)式是生成器的聲明性定義,與列表推到的語(yǔ)法類(lèi)似,只是生成元素是惰性的;
def gen_func():
print('first yield')
yield 'first'
print('second yield')
yield 'second'
l = [x for x in gen_func()]
for x in l:
print(x)
print()
ge = (x for x in gen_func())
print(ge)
for x in ge:
print(x)
# first yield
# second yield
# first
# second
#
# <generator object <genexpr> at 0x7f78ff5dfd60>
# first yield
# first
# second yield
# second
使用生成器表達(dá)式實(shí)現(xiàn)word analyzer
import re
from dis import dis
class WordAnalyzer:
reg_word = re.compile('\w+')
def __init__(self, text):
# self.words = self.__class__.reg_word.findall(text)
self.text = text
def __iter__(self):
# g = self.__class__.reg_word.finditer(self.text)
# print(g)
# for match in g:
# yield match.group()
ge = (match.group() for match in self.__class__.reg_word.finditer(self.text))
print(ge)
return ge
def iter_word_analyzer():
wa = WordAnalyzer('this is mango word analyzer')
print('start for wa')
for w in wa:
print(w)
print('start while wa_iter')
wa_iter = iter(wa)
while True:
try:
print(next(wa_iter))
except StopIteration as e:
break;
iter_word_analyzer()
# start for wa
# <generator object WordAnalyzer.__iter__.<locals>.<genexpr> at 0x7f4178189200>
# this
# is
# mango
# word
# analyzer
# start while wa_iter
# <generator object WordAnalyzer.__iter__.<locals>.<genexpr> at 0x7f4178189200>
# this
# is
# mango
# word
# analyzer
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python實(shí)例解析圖像形態(tài)學(xué)運(yùn)算技術(shù)
形態(tài)學(xué)處理方法是基于對(duì)二進(jìn)制圖像進(jìn)行處理的,卷積核決定圖像處理后的效果。本文將為大家詳細(xì)介紹一下OpenCV中的圖像形態(tài)學(xué),感興趣的可以了解一下2022-03-03
pycharm沒(méi)有找到manage?repositories按鈕的解決辦法
這篇文章主要給大家介紹了關(guān)于pycharm沒(méi)有找到manage?repositories按鈕的解決辦法,pycharm是用來(lái)寫(xiě)python的可視化代碼軟件,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
使用Keras訓(xùn)練好的.h5模型來(lái)測(cè)試一個(gè)實(shí)例
這篇文章主要介紹了使用Keras訓(xùn)練好的.h5模型來(lái)測(cè)試一個(gè)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
PyTorch如何搭建一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)
這篇文章主要介紹了PyTorch如何搭建一個(gè)簡(jiǎn)單的網(wǎng)絡(luò),幫助大家更好的理解和學(xué)習(xí)PyTorch,感興趣的朋友可以了解下2020-08-08
PyTorch常用函數(shù)torch.cat()中dim參數(shù)使用說(shuō)明
這篇文章主要為大家介紹了PyTorch常用函數(shù)torch.cat()中dim參數(shù)使用說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
python的即時(shí)標(biāo)記項(xiàng)目練習(xí)筆記
這篇文章主要介紹了python的即時(shí)標(biāo)記項(xiàng)目練習(xí)筆記,本文是閱讀《python基礎(chǔ)教程》一書(shū)的動(dòng)手實(shí)踐項(xiàng)目,需要的朋友可以參考下2014-09-09

