1.理论知识:什么是生成器?
生成器的本质就是迭代器。生成器和迭代器也有不同,唯一的不同就是:迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。生成器是需要我们自己用python代码构建的工具。最大的区别也就如此了。
2.生成器的构建方式?
在python中有三种方式来创建生成器:
1. 通过生成器函数
2. 通过生成器推导式
3. python内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数而已)
2.1)通过生成器函数构建生成器
#普通函数 def func(): print(11) return 22 ret=func() print(ret) #将函数中return换成yield,这样func就不是函数了。而是一个生成器函数 def func(): print(11) yield 22 ret=func() print(ret)
运行结果:
#普通函数运行结果
11 22
#生成器函数运行结果 <generator object func at 0x02D9EE30>
由于函数中存在yield,那么这个函数就是一个生成器函数.在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器对象
2.2)生成器函数如何取值
生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值。所以我们可以直接执行next()来执行以下生成器
def func(): print('111') yield 222
genner=func() # 这个时候函数不会执⾏. ⽽是获取到⽣成器
ret=genner.__next__() print(ret) # 这个时候函数才会执⾏
运行结果:
111
222
def func(): print("111") yield 222 print("333") yield 444 gener = func() ret = gener.__next__() print(ret) ret2 = gener.__next__() print(ret2) #ret3 = gener.__next__() # 最后⼀个yield执⾏完毕. 再次__next__()程序报错 #print(ret3) 运行结果: 111 222 333 444 Process finished with exit code 0
当程序运行完最后一个yield,那么后面继续运行next()程序会报错,一个yield对应一个next,next超过yield数量,就会报错,与迭代器一样。
yield与return的区别:
return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。
yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。
#return
def eat(): lst = [] for i in range(1,10000): lst.append('包子'+str(i)) return lst e = eat() print(e) #yield def eat(): for i in range(1,10000): yield '包子'+str(i) e=eat() for i in range(200): a=next(e) print(a) for i in range(300): b=next(e) print(b)
运行结果:
return生成列表
yield生成的是值,而且还可以保留上次的位置。暂用空间更小
yield from函数
# 对比yield 与 yield from def func(): lst = ['卫龙','老冰棍','北冰洋','牛羊配'] yield lst g = func() print(g) print(next(g)) # 只是返回一个列表 def func(): lst = ['卫龙','老冰棍','北冰洋','牛羊配'] yield from lst g = func() print(g) # 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。 print(next(g)) print(next(g)) print(next(g)) print(next(g)) ''' yield from ['卫龙','老冰棍','北冰洋','牛羊配'] 等同于: yield '卫龙' yield '老冰棍' yield '北冰洋' yield '牛羊配' '''
yield from 是将列表中的每一个元素返回,所以 如果写两个yield from 并不会产生交替的效果
def func(): lst1 = ['卫龙','老冰棍','北冰洋','牛羊配'] lst2 = ['馒头','花卷','豆包','大饼'] yield from lst1 yield from lst2 g = func() for i in g: print(i)