Python函式式程式設計指南(三) 迭代器

2021-09-25 19:56:08 字數 3430 閱讀 8732

python generators(生成器)

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

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

生成器的特點

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

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

在python中,yield就是這樣的乙個生成器。

yield 生成器的執行機制:

當你問生成器要乙個數時,生成器會執行,直至出現 yield 語句,生成器把 

yield 的引數給你,之後生成器就不會往下繼續執行。 當你問他要下乙個數時,他會從上次的狀態。開始執行,直至出現yield語句,把引數給你,之後停下。如此反覆 直至退出函式。(以上關於yield的描述,在後面列舉乙個簡單的例子來解釋這段話)

yield的使用

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

c = h()

#h()包含了yield關鍵字

#返回值

c.next()

每當呼叫一次迭代器的next函式,生成器函式執行到yield之處,返回yield後面的值且在這個地方暫停,所有的狀態都會被保持住,直到下次next函式被呼叫,或者碰到異常迴圈退出。

下面,來看看以下的例子**吧,是用來說明yield執行機制的。

deffib(max):

a, b =

1, 1

while a < max:

yield a

#generators return an iterator that returns a stream of values.

a, b = b, a+b

程式執行:

for n

in fib(

15):

print n

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

程式第一次呼叫時:

deffib(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物件。

等待第三次的呼叫....

deffib(max):

a, b =

1, 1

while a < max:

yield a

a, b = b, a+b

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

通過使用生成器的語法,可以免去寫迭代器類的繁瑣**,如,上面的例子使用迭代類來實現,**如下:

class

fib:

def__init__

(self, max)

:

self.max = max

def__iter__

(self)

:

self.a =

0self.b =

1return

self

defnext

(self)

:

fib =

self.a

if fib >

self.

max:

raise stopiteration

self.a,

self.b =

self.b,

self.a +

self.b

return fib

yield其他例子展示:排列,組合

#生成全排列    

defperm

(items, n = none):

if n

isnone:

n = len(items)

for i

in range(len(items)):

v = items[i:i+

1]if n==

1:yield v

else:

rest = items[:i] + items[i+

1:]for p

in perm(rest, n

-1):

yield v + p

defcomb

(items, n = none):

if n

isnone:

n = len(items)

else:

for i

in range(len(items)):

v = items[i:i+

1]if

1 == n:

yield v

else:

rest = items[i+

1:]for c

in comb(rest, n

-1):

yield v + c

Python函式式程式設計指南(一) 概述

這大概算是python最難啃的一塊骨頭吧。在我python生涯的這一年裡,我遇到了一些pythoner,他們毫無例外地完全不會使用函式式程式設計 有些人喜歡稱為pythonic 比如,從來不會傳遞函式,不知道lambda是什麼意思,知道列表展開但從來不知道用在 對python不提供經典for迴圈感到...

Python函式式程式設計指南(一) 概述

這大概算是python最難啃的一塊骨頭吧。在我python生涯的這一年裡,我遇到了一些pythoner,他們毫無例外地完全不會使用函式式程式設計 有些人喜歡稱為pythonic 比如,從來不會傳遞函式,不知道lambda是什麼意思,知道列表展開但從來不知道用在 對python不提供經典for迴圈感到...

Python函式式程式設計指南(一) 概述

這大概算是python最難啃的一塊骨頭吧。在我python生涯的這一年裡,我遇到了一些pythoner,他們毫無例外地完全不會使用函式式程式設計 有些人喜歡稱為pythonic 比如,從來不會傳遞函式,不知道lambda是什麼意思,知道列表展開但從來不知道用在 對python不提供經典for迴圈感到...