1. 程式人生 > >yield與yield from

yield與yield from

back 下一個 value 處理 list 返回 lose 接受 iterable

yield

通過yield返回的是一個生成器,yield既可以產出值又可以生成值,yield可以用next()來啟動生成器,同時可以用send向生成器傳遞值;在初次啟動生成器時,需調用next()或send(None)來激活生成器,一個yield對應一個send或next(),當send或next()個數超過yield個數時,會拋出StopIteration

 1 def gen_yield():
 2     value = yield 1
 3     print(value)
 4     value = yield 2
 5     print(value)
 6     value = yield
3 7 print(value) 8 return "end" 9 10 11 gen = gen_yield() 12 13 print(next(gen)) 14 print(gen.send("a")) 15 print(gen.send("b")) 16 print(gen.send("c"))

next(gen)激活生成器yield 1,返回1,並將生成器掛起;gen.send("a")會將"a"傳遞給value = yield 1,此時value="a",打印出a,返回2,將生成器掛起;gen.send("b")將"b"傳遞給value = yield 2,此時value="b",打印"b"並返回3,將生成器掛起;gen.send("c")將"c"傳遞給value = yield 3,此時value="c",打印"c",由於後面沒有生成器了,會拋出StopIteration異常。

1
a
2
b
3
c
Traceback (most recent call last):
    print(gen.send("c"))
StopIteration: end

close()/throw() 關閉/暫停 生成器

 1 def gen_yield():
 2     try:
 3         yield "a"
 4     except StopIteration:
 5         pass
 6     yield "b"
 7     yield "c"
 8     return "end"
 9 
10 
11 gen = gen_yield()
12 13 print(next(gen)) 14 gen.close() 15 print(111) 16 print(next(gen))

close()是關閉生成器,當生成器執行了close()方法後,即使做了異常處理,與yield相關的語句不會再執行。

throw()相當於中斷、暫停生成器,通過throw()拋出異常後,當異常處理後生成器會執行下一個yield,下一個yield之後的上長期不再受throw()影響。

 1 def gen_yield():
 2     try:
 3         yield "a"
 4     except Exception:
 5         pass
 6     yield "b"
 7     yield "c"
 8     return "end"
 9 
10 
11 gen = gen_yield()
12 
13 print(next(gen))
14 print(gen.throw(Exception))
15 print(111)
16 print(next(gen))

result:

a
b
111
c

yield from

yield from類似於yield,但yield from後面必須接一個可叠代的對象,返回該叠代對象的iter,yield則直接返回接受的對象

def gen_yield(iterable):
    yield iterable


def gen_yield_from(iterable):
    yield from iterable


for value in gen_yield([1, 2, 3]):
    print("yield:{}".format(value))
for value in gen_yield_from([1, 2, 3]):
    print("yield from:{}".format(value))
result:
yield
:[1, 2, 3] yield from:1 yield from:2 yield from:3

yield from會在調用方與子生成器之間建立雙向通道,即yield from後可以接受一個生成器函數,調用方通過send可以直接傳遞數據給子生成器,同時yield from可以接受子生成器返回的數據

 1 def gen_yield():
 2     """
 3     子生成器
 4     :return: 
 5     """
 6     nums = []
 7     i = 1
 8     while i < 4:
 9         n = yield i
10         print("receive {}".format(n))
11         i += 1
12         nums.append(n)
13     return nums
14 
15 
16 def gen_yield_from():
17     val = yield from gen_yield()
18     return val
19 
20 
21 gen_value_list = [100, 200, 300]
22 # 調用方
23 gen = gen_yield_from()
24 # send(None) 激活生成器
25 print("yield return {}".format(gen.send(None)))
26 j = 0
27 while j < 3:
28     try:
29         print("yield return {}".format(gen.send(gen_value_list[j])))
30     except StopIteration as e:
31         print(e)
32     j += 1
gen激活生成器後會通過send發送數據,數據會直接傳遞給子生成器gen_yield
執行結果
yield return 1
receive 100
yield return 2
receive 200
yield return 3
receive 300
[100, 200, 300]

yield與yield from