Python生成器 yield的使用

2021-07-10 13:57:54 字數 2962 閱讀 4319

通過列表生成式,我們可以直接建立乙個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立乙個包含100萬個元素的列表,不僅占用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素占用的空間都白白浪費了。

所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間在python中,這種一邊迴圈一邊計算的機制,稱為生成器(generator)。

生成器是乙個包含了特殊關鍵字yield的函式。當被呼叫的時候,生成器函式返回乙個生成器。可以使用send,throw,close方法讓生成器和外界互動。

生成器也是迭代器,但是它不僅僅是迭代器,擁有next方法並且行為和迭代器完全相同。所以生成器也可以用於python的迴圈中。

生成器是這樣乙個函式,它記住上一次返回時在函式體中的位置。對生成器函式的第二次(或第 n 次)呼叫跳轉至該函式中間,而上次呼叫的所有區域性變數都保持不變。

生成器不僅「記住」了它的資料狀態;生成器還「記住」了它在流控制構造(在命令式程式設計中,這種構造不只是資料值)中的位置。

生成器是乙個函式,而且函式的引數都會保留。

迭代到下一次的呼叫時,所使用的引數都是第一次所保留下的,即是說,在整個所有函式呼叫的引數都是第一次所呼叫時保留的,而不是新建立的。

當你問生成器要乙個數時,生成器會執行,直至出現 yield 語句,生成器把 yield 的引數給你,之後生成器就不會往下繼續執行。 當你問他要下乙個數時,他會從上次的狀態開始執行,直至出現yield語句,把引數給你,之後停下。如此反覆,直至退出函式。

在python中,當你定義乙個函式,使用了yield關鍵字時,這個函式就是乙個生成器,它的執行會和其他普通的函式有很多不同,函式返回的是乙個物件,而不是你平常所用return語句那樣,能得到結果值。如果想取得值,得呼叫next()函式

例子一:

#! /usr/bin/env python

#coding=utf-8

deffib

():

a,b = 0,1

while

1: yield b

a,b = b,a+b

#yield a

if __name__ == '__main__':

f = fib() #函式返回的是乙個物件

for i in range(6):

print f.next()#呼叫next()函式取得值

例子二:

def

fib(max):

a, b = 1, 1

while a < max:

yield a

a, b = b, a+b

程式執行:

for n in fib(15):  

print n

從前面的執行機制描述中,可以獲知,程式執行到yield這行時,就不會繼續往下執行。而是返回乙個包含當前函式所有引數狀態的iterator物件。目的就是為了第二次被呼叫時,能夠訪問到函式所有的引數值都是第一次訪問時的值,而不是重新賦值

程式第一次呼叫時:

def

fib(max):

a, b = 1, 1

while a < max:

yield a #這時a,b值分別為1,1,當然,程式也在執行到這時,返回

a, b = b, a+b

程式第二次呼叫時:

從前面可知,第一次呼叫時,a,b=1,1,那麼,我們第二次呼叫時(其實就是呼叫第一次返回的iterator物件的next()方法),程式跳到yield語句處

執行a,b = b, a+b語句,此時值變為:a,b = 1, (1+1) => a,b = 1, 2

程式繼續while迴圈,當然,再一次碰到了yield a 語句,也是像第一次那樣,儲存函式所有引數的狀態,返回乙個包含這些引數狀態的iterator物件。

等待第三次的呼叫….

通過上面的分析,可以依次類推的展示了yield的詳細執行過程!

而將上述過程用迭代器實現如下:

#! /usr/bin/env python

#coding=utf-8

class

fib:

def__init__

(self, max):

self.max = max

def__iter__

(self):

self.a = 0

self.b = 1

return self

defnext

(self):

fib = self.a

if fib > self.max:

raise stopiteration

self.a, self.b = self.b, self.a + self.b

return fib

if __name__ == '__main__':

for f in fib(6):

print f

結果:

011

235

很顯然,沒有生成器簡潔,通過使用生成器的語法,可以免去寫迭代器類的繁瑣**。

Python之生成器(yield)

這裡是一段防爬蟲文字,請讀者忽略。本文原創首發於csdn,作者idys 部落格首頁 生成器函式 迭代器一定是可迭代物件,可迭代物件不一定是迭代器 def inc for i in range 5 yield i print type inc print type inc x inc print ty...

python中生成器yield

def yield demo for x in range 3 yield x print 生成器後一行 a yield demo print a 這裡的a是乙個生成器物件 可以用for迴圈來遍歷生成器物件裡的元素 for i in a print i 那麼yield的工作過程是怎麼樣的呢?可以通過...

生成器 PHP的生成器yield 原創

在php 5.5中,php多了乙個新的特性,那就是生成器 generator 生成器提供了一種更簡單的方法來實現簡單的物件迭代。下面的manual的引用 生成器提供了一種更容易的方法來實現簡單的物件迭代,相比較定義類實現 iterator 介面的方式,效能開銷和複雜性大大降低。生成器允許你在 for...