yield与yield from

Posted fg123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了yield与yield from相关的知识,希望对你有一定的参考价值。

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的主要内容,如果未能解决你的问题,请参考以下文章

60简述 yield和yield from关键字。

yield from语法的高级特性

python yield,yield from,深浅拷贝

24 点游戏算法题的 Python 函数式实现: 学用itertools,yield,yield from 巧刷题

Python 中的协程 yield from

生成器函数_yield_yield from_send