目录://www.greatytc.com/p/863c446364a8
生成器
1、什么是生成器?
Python社区,生成器与迭代器看成一种,生成器的本质就是迭代器
2、生成器和迭代器的区别?
生成器是我们用Python代码构建的数据结构。迭代器都是提供的,或者转换得来的
3、获取生成器的三种方式?
(1) 生成器函数
(2) 生成器表达式
(3) python内置函数或模块
注:(1)和(3)本质是差不多的,(1)是自己写的函数,而(3)是Python内置提供的函数。
4、生成器函数
首先我们先自己定义一个普通函数:
def outer():
print(123)
return 111
ret=outer()
print(ret)
运行结果为:
123
111
然后我们再来构建一个生成器
将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数
def outer():
print(123)
yield 111
ret=outer()
print(ret)
运行结果为:
<generator object outer at 0x03FA9B40>
我们将return更改为yield后,输出的结果为什么和普通函数的结果不同呢?
由于函数中存在yield,那么这个函数就是一个生成器函数,我们在执行这个函数的时候是获取这个生成器对象,可以直接执行next()来执行以下生成器。
def outer():
print(123)
yield 111
ret=outer()
print(next(ret))
运行结果为:
123
111
这个时候我们输出的结果就是我们想要的了。当然我们可以写多个yield,一个yield对应一个next。
def outer():
print(111) #只是打印输出,并不是取值
print(222)
yield 3
a=1
b=2
c=a+b
print(c)
yield 4
ret=outer()
print(next(ret)) #取到值3
print(next(ret))
print(next(ret)) 当我们的next多与yield时,运行结果就会报错。
运行结果为:
print(next(ret)) StopIteration
next超过yield数量,就会报错,与迭代器一样。
5、return和yield区别:
return:函数中只存在一个return结束函数,并且给函数的执行者返回值
yield:只要函数中有yield那么他就是生成器函数而不是函数。生成器函数中可以存在多个yield,yield不会结束生成器函数,一个yield对应一个next。
实例:
我们有一个这样的情景:快过春节了,校长给全校学生准备了新年礼物,但是校长并不知道全校人数,所以他就特别慷慨地准备了5000份,他把所有的礼物都带到了学校。
def outer():
li= []
for i in range(1,5001):都放到
li.append("第{}份礼物".format(i))
return li
ret=outer()
print(ret)
这样做没有问题,但是我们由于学生没有那么多,只有3000个左右,剩下的2000个礼物,就只能占着一定的空间,放在一边了。如果校长送一个学生买一个礼物,那么这就不会占用太多空间存储了。
def gen_outer():
for i in range(1,5001):
yield "第{}份礼物".format(i)
ret=gen_outer()
for i in range(200):
print(next(ret))
for i in range(200):
print(next(ret))
这两者的区别:
第一种是直接把礼物都买了,占用内存。
第二种是送一个学生买一个礼物,非常的节省内存,而且还可以保留上次的位置。
6、yield from
首先我们先通过一个程序来说明yield from 的功能。
首先没有yield from 的程序
def outer():
li=[1,2,3,4,5 ]
yield li
ret=outer()
print(next(ret))
运行结果为:
[1, 2, 3, 4, 5]
有yield from的程序
def outer():
li=[1,2,3,4,5 ]
yield from li #相当于yield1 yield2 ...... #将li这个列表变成了一个迭代器返回
ret=outer()
print(next(ret))
运行结果为:
1
可以发现有了yield from 后将li这个列表变成了一个迭代器返回。它是将列表中的每一个元素返回。
当我们写两个yield from时:
def outer():
lst1 = ['a','b','c','d']
lst2 = ['e','f','g','h']
yield from lst1
yield from lst2
ret = outer()
for i in range(8):
print(next(ret))
运行结果为:
a
b
c
d
e
f
g
h
由于yield from 是将列表中的每一个元素返回,所以 如果写两个yield from 并不会产生交替的效果