1. 程式人生 > >迭代器_iter_和生成器yield

迭代器_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()方法的迭代器物件,它在容器

PythonIterator生成器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中的iteratoryield生成器(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

IteratorListIterator

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)不能使用這種方式