Python yield

yield

在Python中,带有yield的函数称为生成器(generator),与return只能返回一次不同,yield一般用于循环内,每次只返回当前循环内的返回值,最后生成的结果可以用迭代器返回,也可以用next()方法一次一次返回。

基础、next()、send()

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> def simpleTem(a):
... print("a=",a)
... b = yield a
... print("b=",b)
... c = yield a + b
... print("c=",c)
... print("b+c=", b+c)
...
>>> t = simpleTem(4)
>>> next(t)
a= 4
4
>>> t.send(5)
b= 5
9
>>> t.send(5)
c= 5
b+c= 11
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

从上面的例子可以看出,与普通函数不同,生成器函数在第一次调用时不会立即执行,只有在调用了next()才开始执行,每次执行到yield表达式就会停止,并将yield后面的值返回,send()函数将值从外部传入生成器内部,send()的参数指定的是上一次被挂起的yield语句的返回值。

yield后面没有另一个yield时,生成器中止,抛出StopIteration

next()也能传递值,不过它传递的是None,相当于send(None),两者作用相同,因此开始调用生成器函数时也可以不通过next()触发生成器,可以用send(None)代替。

yield from

yield from用于将生成器的部分操作委派给另一个子生成器,或是替代循环写法,yield from后面添加的为可迭代对象,可以是普通可迭代对象,也可以是生成器。

替代for循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> def gen():
... for c in "AB":
... yield c
... for i in range(3):
... yield i
...
>>> list(gen())
['A', 'B', 0, 1, 2]
>>> def gen():
... yield from "AB"
... yield from range(3)
...
>>> list(gen())
['A', 'B', 0, 1, 2]

子生成器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 子生成器,接收进来的值,计算平均值
def averager():
total = 0
count = 0
average = None
while True:
# term 接收进来的值,直到值为None
term = yield
if term is None:
break
total += term
count += 1
average = total/count
return average

def grouper(result, key):
while True:
# 生成器averager()结束,才会赋值给result
result[key] = yield from averager()

if __name__ == "__main__":
result = {}
key = "test"
values = [44,66,77]
group = grouper(result, key)
# next()先执行,启动生成器
next(group)
for value in values:
group.send(value)
# send(None)以关闭循环
group.send(None)
print(result)

输出:
{'test': 62.333333333333336}

参考资料:
简书Levi__s
HatBoy的博客


- - END - -


腾讯云
0%