python generators(生成器)
生成器是這樣乙個函式,它記住上一次返回時在函式體中的位置。對生成器函式的第二次(或第 n 次)呼叫跳轉至該函式中間,而上次呼叫的所有區域性變數都保持不變。
生成器不僅「記住」了它資料狀態;生成器還「記住」了它在流控制構造(在命令式程式設計中,這種構造不只是資料值)中的位置。
生成器的特點:
生成器是乙個函式,而且函式的引數都會保留。
迭代到下一次的呼叫時,所使用的引數都是第一次所保留下的,即是說,在整個所有函式呼叫的引數都是第一次所呼叫時保留的,而不是新建立的
在python中,yield就是這樣的乙個生成器。
yield 生成器的執行機制:
當你問生成器要乙個數時,生成器會執行,直至出現 yield 語句,生成器把
yield 的引數給你,之後生成器就不會往下繼續執行。 當你問他要下乙個數時,他會從上次的狀態。開始執行,直至出現yield語句,把引數給你,之後停下。如此反覆 直至退出函式。(以上關於yield的描述,在後面列舉乙個簡單的例子來解釋這段話)
yield的使用:
在python中,當你定義乙個函式,使用了yield關鍵字時,這個函式就是乙個生成器,它的執行會和其他普通的函式有很多不同,函式返回的是乙個物件,而不是你平常 所用return語句那樣,能得到結果值。如果想取得值,那得呼叫next()函式,如:
每當呼叫一次迭代器的next函式,生成器函式執行到yield之處,返回yield後面的值且在這個地方暫停,所有的狀態都會被保持住,直到下次next函式被呼叫,或者碰到異常迴圈退出。
c = h()
#h()包含了yield關鍵字
#返回值
c.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迴圈感到...