python关键字from,Python 中的 yield from 关键字
Python 3.3 新增 yield from 語(yǔ)法,是理解協(xié)程的基礎(chǔ)
#0 了解一下 itertools.chain
itertools.chain() 方法可以將不同的迭代類型連接起來進(jìn)行 for 循環(huán)遍歷。
from itertools import chain
lst = [1,2,3]
dic = {
"tom":"www.tom.com",
"bob":"bob.com"
}
# 使用 chain 方法可以直接對(duì)三個(gè)進(jìn)行 for 循環(huán)
for value in chain(lst,dic,range(5,10)):
print(value)
>>>
1
2
3
tom
bob
5
6
7
8
9
那么 itertools.chain() 是如何實(shí)現(xiàn)的呢?
# chain 的實(shí)現(xiàn)方法
# *args
# **kwargs
def chainer(*args, **kwargs):
for iterable in args:
for value in iterable:
yield value
for value in chainer(lst,dic,range(5,10)):
print(value)
>>>
1
2
3
tom
bob
5
6
7
8
9
有了 yield from之后,我們還可以進(jìn)一步少些代碼:
# chain 的實(shí)現(xiàn)方法
# *args
# **kwargs
def chainer(*args, **kwargs):
for iterable in args:
yield from iterable
for value in chainer(lst,dic,range(5,10)):
print(value)
>>>
1
2
3
tom
bob
5
6
7
8
9
看,效果其實(shí)一模一樣!應(yīng)該可以大致感覺到y(tǒng)ield from的特性了吧!yield from 后面操作一個(gè) iterable 類型的對(duì)象可以直接獲取到 iterable 類型的對(duì)象的值并返回。而 yield則不一樣!
#1 yield from 和 yield 的區(qū)別
def g1(iterable):
yield range(10)
for v in g1(range(10)):
print(v)
>>>
range(0, 10)
def g2(iterable):
yield from range(10)
for v in g2(range(10)):
print(v)
>>>
0
1
2
3
4
5
6
7
8
9
#2 yield from 高級(jí)特性及 Coroutine 實(shí)現(xiàn)
1.main 調(diào)用方,func_yield_from 委托生成器, iterable 子生成器
2.yield from 會(huì)在調(diào)用方和子生成器直接建立一個(gè)通道,雙向通道,可以互相通
信
def func_yield_from(iterable):
yield from iterable
def main():
g = func_yield_from(range(10))
g.send(None)
看一個(gè)具體的實(shí)例:
final_result = {}
# 子生成器
def sum_sales(product_name):
total = 0
nums = []
while True:
x = yield
if x:
print(product_name + "銷量:", x)
# 當(dāng) send None 的時(shí)候,跳出 while 循環(huán)
if not x:
break
total += x
nums.append(x)
return total, nums
# 委托生成器
def middle(key):
while True:
final_result[key] = yield from sum_sales(key)
print("Complete!",final_result[key])
# 調(diào)用方
def main():
dataset = {
'apple': [1200, 1330, 500],
'orange': [400, 600, 1000],
'banana': [100, 500, 50]
}
for key,dataset in dataset.items():
print('key:', key)
print('dataset:',dataset)
m = middle(key)
# 預(yù)激 middle 協(xié)程
m.send(None)
# 給協(xié)程傳遞每一組的值
for value in dataset:
m.send(value)
# 傳遞 None 終止 while 循環(huán)
m.send(None)
print(final_result)
if __name__ == "__main__":
main()
輸出如下:
>>>
key: apple
dataset: [1200, 1330, 500]
apple銷量: 1200
apple銷量: 1330
apple銷量: 500
Complete! (3030, [1200, 1330, 500])
key: orange
dataset: [400, 600, 1000]
orange銷量: 400
orange銷量: 600
orange銷量: 1000
Complete! (2000, [400, 600, 1000])
key: banana
dataset: [100, 500, 50]
banana銷量: 100
banana銷量: 500
banana銷量: 50
Complete! (650, [100, 500, 50])
{'apple': (3030, [1200, 1330, 500]), 'orange': (2000, [400, 600, 1000]), 'banana': (650, [100, 500, 50])}
#3 yield from 背后做的事情
try-catch 異常
# 沒有 yield 的情況
def sum_sales(product_name):
total = 0
nums = []
while True:
x = yield
if x:
print(product_name + "銷量:", x)
# 當(dāng) send None 的時(shí)候,跳出 while 循環(huán)
if not x:
break
total += x
nums.append(x)
return total, nums
if __name__ == "__main__":
gen = sum_sales('apple')
gen.send(None)
gen.send(1200)
gen.send(1000)
gen.send(800)
# gen.send(None)
>>>
apple銷量: 1200
apple銷量: 1000
apple銷量: 800
去掉 gen.send(None)注釋之后:
>>>
apple銷量: 1200
apple銷量: 1000
apple銷量: 800
Traceback (most recent call last):
File "/4_yield_from_try_catch_except.py", line 27, in
gen.send(None)
StopIteration: (3000, [1200, 1000, 800])
可見拋出了一個(gè)異常,并返回了我們需要的值。所以,在沒有 yield from 的情況下,我們需要捕獲這個(gè)異常:
if __name__ == "__main__":
gen = sum_sales('apple')
gen.send(None)
gen.send(1200)
gen.send(1000)
gen.send(800)
try:
gen.send(None)
except StopIteration as e:
result = e.value
print(result)
這樣,就能正常了,不僅不會(huì)拋出異常,還能夠獲取到我們需要的值了:
apple銷量: 1200
apple銷量: 1000
apple銷量: 800
(3000, [1200, 1000, 800])
所以說,單純不用yield from的話,我們就需要寫異常處理之類的邏輯,進(jìn)一步減少代碼量。
總結(jié)
以上是生活随笔為你收集整理的python关键字from,Python 中的 yield from 关键字的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php中url问题,PHP中URL域的解
- 下一篇: 清空list_3. Python3轻食丨