生成器的本质就是迭代器。
生成器包括两种:生成器函数和生成器表达式
1.生成器函数
一个包含yield关键字的函数就是一个生成器函数。并且yield不能和return共用,并且yield只能用在函数内。
(1).生成器函数执行之后会得到一个生成器作为返回值,并不会执行函数体。
(2).执行了__next__()方法之后才会执行函数体,并且获得返回值。
(3).next()内置方法,内部调用生成器函数的__next__()方法。
(3).yield和return相同的是可以返回值,但是不同的是yield 不会结束函数
练习1:创建一个生成器,并且调用
# 注意调用生成器,函数体是不会执行的,会返回一个生成器对象
def generator():
print('xxxx')
yield
ret = generator() # 返回一个生成器对象
print(ret) # 返回生成器对象的地址 <generator object generator at
0x0000000002754938>
ret.__next__() # 调用__next__ 方法执行函数体,遇到yield停止 xxxx
ret.__next__() # 报错,因为没有遇到yield
练习2:创建一个生成器,并且设置返回值
def generator():
print('xxxx')
yield 1
ret = generator() # 返回一个生成器对象
a = next(ret) # 调用__next__方法 xxxx 实际yield返回的1 已经有了,只是需要变量来承
接
# print(a) # 1 返回yield 的值
练习3:创建生成器,定义多个yield 值,
def generator():
print('xxxx')
yield 1
print('oooo')
yield 2
ret = generator() # 返回一个生成器对象
a = next(ret) # 调用__next__方法 xxxx
print(a) # 1
a = next(ret)
print(a) # 2
练习4:创建生成器,生成200万桶康师傅方便面。
def ksf():
for i in range(2000000):
yield '正在生成第%s桶方便面' % i
ret = ksf()
for i in ret:
print(i)
2.send()
send 获取下一个值的效果和next()基本一致,只是在获取下一个值的时候,给上一yield的位置传递一个数据
使用send的注意事项
(1).第一次使用生成器的时候 是用next获取下一个值
(2).最后一个yield不能接受外部的值
练习1:使用send()方法给yield传递参数
练习2.计算移动平均值
def func_avg():
avg = 0 # 平均值
totle = 0 # 总和
get_num = 0 # 传递的数
count = 1 # 传递值的个数
while True:
get_num = yield avg
totle = totle + get_num
avg = totle / count
count += 1
fun = func_avg()
next(fun)
print(fun.send(10)) # 10.0
print(fun.send(20)) # 15.0
print(fun.send(30)) # 20.0
3. yield from
yield from 循环遍历容器类型
练习1:使用for循环取出g1生成器中所有的值。
def gen1():
for i in 'abc':
yield i
for j in range(4):
yield j
g = gen1()
for k in g:
print(k)
练习2:使用 yield from 遍历出可变数据类型中的数据。
def gen1():
yield from 'abc'
yield from range(4)
g = gen1()
for k in g:
print(k)
4.生成器表达式
将列表表达式的[ ] 改成()即可
g = (i for i in range(10))
print(g) # 返回的生成器地址
for j in g:
print(j)