什么是生成器?这个概念比较模糊,各种文献都有不同的理解,但是核心基本相同。生成器的本质就是迭代器,在python社区中,大多数时候都把迭代器和生成器是做同一个概念。不是相同么?为什么还要创建生成器?生成器和迭代器也有不同,唯一的不同就是:迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。生成器是需要我们自己用python代码构建的工具。最大的区别也就如此了
在python中有三种方式来创建生成器:
我们先看一个很简单的函数:
def func(): print('in func1') return 22 func() print(func()) >>> in func1 in func1 22
将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数
def func(): print('in func1') yield 22 #函数中存在yield,那么这个函数就是一个生成器函数 func() print(func()) >>> <generator object func at 0x0000018C4DED2E48>
运行的结果和最上面的不一样,为什么呢?? 由于函数中存在yield,那么这个函数就是一个生成器函数.
生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值。所以我们可以直接执行next()来执行以下生成器
def func(): print('in func1') yield 22 print(func()) print(next(func())) >>> <generator object func at 0x000002CF72A02EC8> in func1 22
举列
我们来看一下这个需求:老男孩向楼下卖包子的老板订购了10000个包子.包子铺老板非常实在,一下就全部都做出来了
def eat(): lst = [] for i in range(1,10000): lst.append('包子'+str(i)) return lst print(eat())
这种方式是可以,但是是个消耗内存的方法;但是我们由于学生没有那么多,只吃了2000个左右,剩下的8000个,就只能占着一定的空间,放在一边了。如果包子铺老板效率够高,我吃一个包子,你做一个包子,那么这就不会占用太多空间存储了,完美..
def eat(): for i in range(1,10): yield '包子'+str(i) e = eat() for i in range(5): print(next(e)) # 多次next包子的号码是按照顺序记录的。 >>> 包子1 包子2 包子3 包子4 包子5
这两者的区别
提供一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回
# 对比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 '牛羊配' '''