#例1. 簡單輸出斐波那契數列前 N 個數
#缺點:該函數可復用性較差,因為 fab 函數返回 None,其他函數無法獲得該函數生成的數列
#要提高 fab 函數的可復用性,最好不要直接打印出數列,而是返回一個 List。
def fab1(max):
n, a, b = 0, 0, 1
while n < max:
print(b,end=' ')
a, b = b, a + b
n = n + 1
fab1(5)
#例 2.
#缺點:該函數在運行中占用的內存會隨着參數 max 的增大而增大,如果要控制內存占用,
#最好不要用 List 來保存中間結果,而是通過 iterable 對象來迭代
def fab2(max):
n, a, b = 0, 0, 1
L = []
while n < max:
L.append(b)
a, b = b, a + b
n = n + 1
return L
#例3
#說明:帶有 yield 的函數不再是一個普通函數,Python 解釋器會將其視為一個 generator,
#調用 fab(5) 不會執行 fab 函數,而是返回一個 iterable 對象!
#在 for 循環執行時,每次循環都會執行 fab 函數內部的代碼,執行到 yield b 時,fab 函數就返回一個迭代值,
#下次迭代時,代碼從 yield b 的下一條語句繼續執行,而函數的本地變量看起來和上次中斷執行前是完全一樣的,
#於是函數繼續執行,直到再次遇到 yield。
def fab3(max):
n, a, b = 0, 0, 1
while n < max:
yield b
# print b
a, b = b, a + b
n = n + 1
f=fab3(5)
print("f是一個可迭代對象,並沒有執行函數")
print(f)
print('fab3返回的是一個iterable 對象,可以用for循環獲取值')
for n in f:
print(n)
#例4: #說明:yield from iterable本質上等於for item in iterable: yield item的縮寫版 def f_wrapper1(f): for g in f: yield g wrap = f_wrapper1(fab3(5)) for i in wrap: print(i,end=' ') print('\n使用yield from代替for循環') def f_wrapper2(f): yield from f#注意此處必須是一個可生成對象 wrap = f_wrapper2(fab3(5)) for i in wrap: print(i,end=' ') print('\n---------------------') print('yield from包含多個子程序') def g(x): yield from range(x, 0, -1) yield from range(x) print(list(g(5))) for g in g(6): print(g,end=',') print('\n---------------------')
注意紅色部分就是替代的部分,yield from iterable本質上等於for item in iterable: yield item的縮寫版
#例5 利用yield from語句向生成器(協程)傳送數據
#傳統的生產者-消費者模型是一個線程寫消息,一個線程取消息,通過鎖機制控制隊列和等待,但一不小心就可能死鎖。
#如果改用協程,生產者生產消息后,直接通過yield跳轉到消費者開始執行,待消費者執行完畢后,換回生產者繼續生產,效率極高:
def consumer_work(len):
# 讀取send傳進的數據,並模擬進行處理數據
print("writer:")
w=''
while True:
w = yield w # w接收send傳進的數據,同時也是返回的數據
print('[CONSUMER] Consuming %s...>> ', w)
w*=len #將返回的數據乘以100
time.sleep(0.1)
def consumer(coro):
yield from coro#將數據傳遞到協程(生成器)對象中
def produce(c):
c.send(None)# "prime" the coroutine
for i in range(5):
print('[Produce] Producing %s----', i)
w=c.send(i)#發送完成后進入協程中執行
print('[Produce] receive %s----', w)
c.close()
c1=consumer_work(100)
produce(consumer(c1))
執行結果:
writer:
[Produce] Producing %s---- 0
[CONSUMER] Consuming %s...>> 0
[Produce] receive %s---- 0
[Produce] Producing %s---- 1
[CONSUMER] Consuming %s...>> 1
[Produce] receive %s---- 100
[Produce] Producing %s---- 2
[CONSUMER] Consuming %s...>> 2
[Produce] receive %s---- 200
[Produce] Producing %s---- 3
[CONSUMER] Consuming %s...>> 3
[Produce] receive %s---- 300
[Produce] Producing %s---- 4
[CONSUMER] Consuming %s...>> 4
[Produce] receive %s---- 400
yield from一般掌握這兩種用法即可;
