迭代器_iter_和生成器yield
一、迭代器
定義:
對於list、string、tuple、dict等這些容器物件,使用for迴圈遍歷是很方便的。在後臺for語句對容器物件呼叫iter()函式。iter()是python內建函式。
iter()函式會返回一個定義了next()方法的迭代器物件,它在容器中逐個訪問容器內的元素。next()也是python內建函式。在沒有後續元素時,next()會丟擲一個StopIteration異常,通知for語句迴圈結束。
迭代器是用來幫助我們記錄每次迭代訪問到的位置,當我們對迭代器使用next()函式的時候,迭代器會向我們返回它所記錄位置的下一個位置的資料。實際上,在使用next()函式的時候,呼叫的就是迭代器物件的_next_方法
(Python3中是物件的_next_方法,Python2中是物件的next()方法)。所以,我們要想構造一個迭代器,就要實現它的_next_方法。但這還不夠,python要求迭代器本身也是可迭代的,所以我們還要為迭代器實現_iter_方法,而_iter_方法要返回一個迭代器,迭代器自身正是一個迭代器,所以迭代器的_iter_方法返回自身self即可。
一些術語的解釋:
1,迭代器協議:物件需要提供next()方法,它要麼返回迭代中的下一項,要麼就引起一個StopIteration異常,以終止迭代
2,可迭代物件:實現了迭代器協議物件。list、tuple、dict都是Iterable(可迭代物件),但不是Iterator(迭代器物件)。但可以使用內建函式iter(),把這些都變成Iterable(可迭代器物件)。
3,for item in Iterable 迴圈的本質就是先通過iter()函式獲取可迭代物件Iterable的迭代器,然後對獲取到的迭代器不斷呼叫next()方法來獲取下一個值並將其賦值給item,當遇到StopIteration的異常後迴圈結束
Python自帶容器物件案例:
# 隨便定義一個list listArray=[1,2,3] # 使用iter()函式 iterName=iter(listArray) print(iterName) # 結果如下:是一個列表list的迭代器 # <list_iterator object at 0x0000017B0D984278> print(next(iterName)) print(next(iterName)) print(next(iterName)) print(next(iterName))#沒有迭代到下一個元素,直接丟擲異常 # 1 # 2 # 3 # Traceback (most recent call last): # File "Test07.py", line 32, in <module> # StopIteration!
Python中一個實現了_iter_方法和_next_方法的類物件,就是迭代器,如下案例是計算菲波那切數列的案例
class Fib(object):
def __init__(self, max):
super(Fib, self).__init__()
self.max = max
def __iter__(self):
self.a = 0
self.b = 1
return self
def __next__(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib
# 定義一個main函式,迴圈遍歷每一個菲波那切數
def main():
# 100以內的數
fib = Fib(100)
for i in fib:
print(i)
# 測試
if __name__ == '__main__':
main()
解釋說明:
在本類的實現中,定義了一個_iter_(self)方法,這個方法是在for迴圈遍歷時被iter()呼叫,返回一個迭代器。因為在遍歷的時候,是直接呼叫的python內建函式iter(),由iter()通過呼叫_iter_(self)獲得物件的迭代器。有了迭代器,就可以逐個遍歷元素了。而逐個遍歷的時候,也是使用內建的next()函式通過呼叫物件的_next_(self)方法對迭代器物件進行遍歷。所以要實現_iter_(self)和_next_(self)這兩個方法。
而且因為實現了_next_(self)方法,所以在實現_iter_(self)的時候,直接返回self就可以。
總結一句話就是:
在迴圈遍歷自定義容器物件時,會使用python內建函式iter()呼叫遍歷物件的_iter_(self)獲得一個迭代器,之後再迴圈對這個迭代器使用next()呼叫迭代器物件的_next_(self)。注意點:_iter_(self)只會被呼叫一次,而_next_(self)會被呼叫 n 次,直到出現StopIteration異常。
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化兩個計數器a,b
def __iter__(self):
return self # 例項本身就是迭代物件,故返回自己
def __next__(self):
self.a, self.b = self.b, self.a + self.b # 計算下一個值
if self.a > 100000: # 退出迴圈的條件
raise StopIteration();
return self.a # 返回下一個值
IJCNLP的例子:
注意:這個例子中沒有__next(self)__,而是使用了yield.
這樣產生的是一個生成器。所以更像下面談到的生成器的用法。
class FlashcardSentences(object):
def __init__(self, num_list):
self.num_list = num_list
def __iter__(self):
for line in self.num_list:
yield line
a=FlashcardSentences([3,2,3,4,5])
'''注意:這是生成器物件'''
print(iter(a))
#<generator object __iter__ at 0x000002A7AC4998E0>
for i in a:
print(i)
//////////////////////////////////////////////////////////////////////////////////
class FlashcardSentences(object):
def __init__(self, filename):
self.filename = filename
def __iter__(self):
for line in open(self.filename, "rb"):
line = line.strip()
line = line.decode("utf8").encode("ascii", "ignore")
_, question, answer = line.split("\t")
qwords = nltk.word_tokenize(question)
awords = nltk.word_tokenize(answer)
yield qwords + awords
二、生成器
作用:
迭代器是一個物件,而生成器是一個函式,迭代器和生成器是python中兩個非常強大的特性,編寫程式時你可以不使用生成器達到同樣的效果,但是生成器讓你的程式更加pythonic。
建立生成器只要在函式中加入yield語句即可。函式中每次使用yield產生一個值,函式就返回該值,然後停止執行,等待被啟用,被啟用後繼續在原來的位置執行。
也就是:每到yield執行完就暫停。
下邊的例子實現了同樣的功能:
注意事項:
生成器是隻能遍歷一次的。
生成器是一類特殊的迭代器。
例子:
#!/usr/bin/env python
#coding=utf-8
def fib():
a,b = 0,1
while 1:
a,b = b,a+b
yield a
for f in fib():
if f < 10000:
print f
else:
break
注意下面的例子:
f=Fib(10)會產生一個生成器,這裡不需要使用iter()函式。
def Fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return '親!沒有資料了...'
# 呼叫方法,生成出10個數來
f=Fib(10)
# 使用一個迴圈捕獲最後return 返回的值,儲存在異常StopIteration的value中
while True:
try:
x=next(f)
print("f:",x)
except StopIteration as e:
print("生成器最後的返回值是:",e.value)
break
def createGenerator():
mylist = range(3)
for i in mylist:
yield i*i
mygenerator = createGenerator() # 建立生成器
print(mygenerator) # mygenerator is an object!
#<generator object createGenerator at 0x000002A7AC499B48>
for i in mygenerator:
print(i)
在CNN情感分析中的例子:
def batch_iter(data, batch_size, num_epochs):
"""
Generates a batch iterator for a dataset.
"""
data = np.array(data)
data_size = len(data)
num_batches_per_epoch = int(len(data)/batch_size) + 1
for epoch in range(num_epochs):
# Shuffle the data at each epoch
shuffle_indices = np.random.permutation(np.arange(data_size))
shuffled_data = data[shuffle_indices]
for batch_num in range(num_batches_per_epoch): #batch_num表示第幾批
start_index = batch_num * batch_size
end_index = min((batch_num + 1) * batch_size, data_size)
yield shuffled_data[start_index:end_index]
相關推薦
迭代器_iter_和生成器yield
一、迭代器 定義: 對於list、string、tuple、dict等這些容器物件,使用for迴圈遍歷是很方便的。在後臺for語句對容器物件呼叫iter()函式。iter()是python內建函式。 iter()函式會返回一個定義了next()方法的迭代器物件,它在容器
Python迭代器Iterator和生成器generator
容器(container) 容器是一種把多個元素組織在一起的資料結構,容器中的元素可以逐個地迭代獲取,可以用in, not in關鍵字判斷元素是否包含在容器中。通常這類資料結構把所有的元素儲存在記憶體中(也有一些特例,並不是所有的元素都放在記憶體,比如迭代器和生成器物件) 可迭代物
php 迭代器與和生成器
php有很多功能強大的介面,其中ArrayAccess 與 Iterator 的配合使用可以讓物件與陣列一樣有著靈活的訪問性。 當然,用ArrayAccess 與 Iterator 配合可以用來對付陣列,但還有一個更好的辦法同則SPL 提供的ArrayIterator 原因就是 : Ar
迭代器(Iterator) 和 生成器 (Generator) (八)
迭代器與生成器這一章節還沒有看的恨透,只把這一章節的例子全看完了,也看懂了。但是自己寫不出這樣優秀的程式碼。這是我缺少的技能。 // 迭代器(Iterator) 和 生成器(Generator) // 迭代器是一種特殊物件
【python 第七日】迭代器類和生成器進階
迭代器中的throw 放出異常,消耗一個yield def gen(): while True: try: yield 'normal value' yield 'normal value 2'
迭代器 (Iterator) 和 生成器 (Generator)
>其他章節請看: > >[es6 快速入門 系列][1] ## 迭代器 (Iterator) 和 生成器 (Generator) ### 試圖解決的問題 ```javascript let colors = ['red', 'blue', 'green', 'yellow'] for(l
Python中的迭代器iterator和yield生成器(constructor)
什麼叫迭代器和可迭代物件? 一、可迭代物件(Iterable) 可以直接作用於for迴圈的物件統稱為可迭代物件(Iterable)。 所有的Iterable均可以通過內建函式iter()來轉變為Iterator。 然後使用它的next()方法呼叫,直
Python學習之路8?叠代器協議和生成器
rep 好處 obj 必須 決定 內容 cnblogs 有用 pri 一 什麽是叠代器協議 1.叠代器協議是指:對象必須提供一個next方法,執行該方法要麽返回叠代中的下一項,要麽就引起一個StopIteration異常,以終止叠代 (只能往後走不能往前退) 2.可叠代對象
php 叠代器與和生成器
表達 fun acc 調用 轉換 叠代 需要 函數 進行 php有很多功能強大的接口,其中ArrayAccess 與 Iterator 的配合使用可以讓對象與數組一樣有著靈活的訪問性。 當然,用ArrayAccess 與 Iterator 配合可以用來對付數組,但還有一個更
Python學習——02-Python基礎——【5-叠代器協議和生成器】
expr filter exp 就是 ati another 檢索 traceback AD 1.叠代器(iterator) 要說生成器,必須首先說叠代器 1.區分iterable,iterator與itertion 講到叠代器,就需要區別幾個概念:iterable,ite
python:從迭代器,到生成器,再到協程的示例程式碼
程式設計師,沒事多練練, 併發,並行程式設計,演算法,設計模式, 這三個方面的知識點,沒事就要多練練,基本功呀。 class MyIterator: def __init__(self, element): self.element = element d
迭代器Iterator和ListIterator
Iterator迭代器 屬於設計模式,提供了一個方法,對集合/容器內的元素進行遍歷,而不用關注底層實現細節,達到資料與上層遍歷解耦的目的.(解耦: 訪問邏輯從不同型別的集合類中抽取出來,接觸兩者間的聯合關係。) Iterator迭代器提供的三種方法:(迭代器直接操作
Python中iteration(迭代)、iterator(迭代器)、generator(生成器)等相關概念的理解
在閱讀Python tutorial類這一章的時候出現了iterator的概念,我是一個是程式設計的半吊子,雖然在其它語言(比如Java和C++)中也聽過這個概念,但是一直沒認真的去理解,這次我參考了一些文章,總結了一些我的看法。 首先,我在理解相關的概念的時
python 叠代器協議和生成器!
為什麽 watermark 叠代 ESS 學習 超出 size oss 都是 一、什麽是叠代器協議 1.叠代器協議是指:對象必須提供一個next方法,執行該方法要麽返回叠代中的下一項,要麽就引起一個stoplteration異常,以終止叠代(只能往後走,不能往前退) 2.可
Java程式設計師從笨鳥到菜鳥之(四十五)大話設計模式(九)迭代器模式和命令模式
歡迎關注微信賬號:java那些事:csh624366188.每天一篇java相關的文章 java交流工作群1: 77800592(已滿) java交流學生群2:234897635(已滿) java交流工作群3:94507287 java交流工作群4: 272265434 我的郵箱:
迭代器模式和組合模式-《Head First 設計模式》
問題彙總 迭代器定義和作用 迭代器遍歷一個聚合物,並將其封裝成另一個物件。 迭代器適用場景 迭代器模式的結構和實現方法 組合模式定義和作用以及適用場景 適用於“整體/部分”的關係結構,用於統一處理所有物件(不分節點還是葉子)。 組合模式結構和實現的兩種方
STL 迭代器失效和運算子過載容易錯誤問題
1.一定要小心迭代器失效 1) 容器本身是空的,使用迭代器前,需要檢驗迭代器是否有效。 2) 容器本身增刪失效,erase返回的是下一個迭代器,容器改變了插入刪除了那麼原來的迭代器就很容易失效。 3)容器存放的資料增刪,容器內儘量存放的是結構體,而不是指標,存放指標很容易導
【Python】迭代器(iterator) vs 生成器(generator)
迭代器(iterator) 在介紹迭代器之前還有一種iterable物件需要簡單的說明。對於iterator和iterable是兩個不同的概念。 iterable iterable是含有__
Python基礎(四)——迭代器/物件,生成器
首先廖雪峰網站寫的內容就我目前初步學習來說,已經相當詳實,知識點平鋪直敘讓人易接受,所以以下內容均作為一種摘記記錄以及補充。 1. 列表生成器 主要目的是建立 list 。多看例子就能清楚: print(list(range(1,10,2))) #[1, 3, 5, 7, 9].生成1~9
C++ STL迭代器原理和簡單實現
### 1. 迭代器簡介 為了提高C++程式設計的效率,STL(Standard Template Library)中提供了許多容器,包括vector、list、map、set等。然而有些容器(vector)可以通過下標索引的方式訪問容器裡面的資料,但是大部分的容器(list、map、set)不能使用這種方式