def jumping_range(N): index = 0 while index < N: # 經過send()發送的信息將賦值給jump jump = yield index # print("jump", jump) if jump is None: jump = 1 index += jump if __name__ == '__main__': itr = jumping_range(5) print(next(itr)) # 1 print(itr.send(2)) # 2 print(next(itr)) # 3 print(itr.send(-1)) #4
if __name__ == '__main__': itr = jumping_range(5) print(next(itr)) print(itr.send(2)) print(next(itr)) print(itr.send(-1)) print(next(itr)) print(next(itr)) try: print(next(itr)) except StopIteration as e: print(e.value)
很少說直接代碼比較 ,下面一個例子函數
用yield實現spa
# 字符串 astr='ABC' # 列表 alist=[1,2,3] # 字典 adict={"name":"wangbm","age":18} # 生成器 agen=(i for i in range(4,8)) def gen(*args, **kw): print(args) for item in args: for i in item: yield i new_list=gen(astr, alist, adict, agen) print(next(new_list)) #print(type(new_list)) #['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]
使用yield from code
# 字符串 astr='ABC' # 列表 alist=[1,2,3] # 字典 adict={"name":"wangbm","age":18} # 生成器 agen=(i for i in range(4,8)) def gen(*args, **kw): for item in args: yield from item new_list=gen(astr, alist, adict, agen) print(list(new_list)) # ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]
由上面兩種方式對比,能夠看出,yield from後面加上可迭代對象,他能夠把可迭代對象裏的每一個元素一個一個的yield出來,對比yield來講代碼更加簡潔,結構更加清晰。orm
yield from 的深層次應用:協程
首先得知道一個概念:對象
一、調用方:調用委派生成器的客戶端(調用方)代碼 二、委託生成器:包含yield from表達式的生成器函數 三、子生成器:yield from後面加的生成器函數
# 子生成器 def average_gen(): total = 0 count = 0 average = 0 while True: new_num = yield average count += 1 total += new_num average = total/count # 委託生成器 def proxy_gen(): while True: yield from average_gen() # 調用方 def main(): calc_average = proxy_gen() next(calc_average) # 預激下生成器 print(calc_average.send(10)) # 打印:10.0 print(calc_average.send(20)) # 打印:15.0 print(calc_average.send(30)) # 打印:20.0 if __name__ == '__main__': main()
send()
直接發送消息給子生成器,而子生成器yield的值,也是直接返回給調用方。
你可能會常常看到有些代碼,還能夠在yield from
前面看到能夠賦值。這是什麼用法?blog
你可能會覺得,子生成器yield回來的值,被委託生成器給攔截了。你能夠親自寫個demo運行試驗一下,並非你想的那樣。
由於咱們以前說了,委託生成器,只起一個橋樑做用,它創建的是一個雙向通道
,它並無權利也沒有辦法,對子生成器yield回來的內容作攔截。文檔
例子:字符串
# 子生成器 def average_gen(): total = 0 count = 0 average = 0 while True: new_num = yield average if new_num is None: break count += 1 total += new_num average = total/count # 每一次return,都意味着當前協程結束。 return total,count,average # 委託生成器 def proxy_gen(): while True: # 只有子生成器要結束(return)了,yield from左邊的變量纔會被賦值,後面的代碼纔會執行。 total, count, average = yield from average_gen() print("計算完畢!!\n總共傳入 {} 個數值, 總和:{},平均數:{}".format(count, total, average)) # 調用方 def main(): calc_average = proxy_gen() next(calc_average) # 預激協程 print(calc_average.send(10)) # 打印:10.0 print(calc_average.send(20)) # 打印:15.0 print(calc_average.send(30)) # 打印:20.0 calc_average.send(None) # 結束協程 # 若是此處再調用calc_average.send(10),因爲上一協程已經結束,將重開一協程 if __name__ == '__main__': main()
結果:it
10.0
15.0
20.0
計算完畢!!
總共傳入 3 個數值, 總和:60,平均數:20.0