生成器使用总结:
1.生成器的好处是可以一边循环一边进行计算,不用一下子就生成一个很大的集合,占用内存空间。生成器的使用节省内存空间。
2.生成器保存的是算法,而列表保存的计算后的内容,所以同样内容的话生成器占用内存小,而列表占用内存大。每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的异常。
3.使用for 循环来遍历生成器内容,因为生成器也是可迭代对象。通过 for 循环来迭代它,不需要关心 StopIteration 异常。但是用for循环调用generator时,得不到generator的return语句的返回值。如果想要拿到返回值,必须用next()方法,且捕获StopIteration错误,返回值包含在StopIteration的value中。
4.在 Python 中,使用了 yield 的函数都可被称为生成器(generator)。生成器是一个返回迭代器的函数,只能用于迭代操作。更简单点理解生成器就是一个迭代器。
5.一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,保存当前所有的运行信息,并返回一个迭代值,下次执行next() 方法时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造中的位置。
当然其实平常很少用到next(),我们直接用for循环就可以遍历一个generator,其实for循环的内部实现就是不停调用next()。
可迭代对象(Iterable)和迭代器(Iterator)的概念:
可迭代对象(Iterable)
可以直接作用于for循环的对象统称为可迭代对象:Iterable。包括集合数据类型(list、tuple、dict、set、str等)和生成器(generator)。
迭代器:Iterator
它表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
把list、dict、str等Iterable变成Iterator可以使用iter()函数:
生成器(generator)本身就是一个迭代器;
list、dict、str等可迭代对象(Iterable) 要使用iter()函数才能变成迭代器(Iterator)
生成器有两种:
生成器函数
生成器表达式
生成器函数的定义:
含有yield语句的函数是生成器函数,此函数被调用将会返回一个生成器对象
简单来说:只要在def中有yield关键字的 就称为 生成器
yield翻译为产生(或生成)
说明:
yield 用于def函数中,目的是将此函数用生成器函数使用
yield 用来生成数据,供迭代器和next(it)函数使用
def myyield():
print("即将生成2")
yield 2
print("即将生成3")
# return '在生成3之前用return返回' 将会发生异常
yield 3
print("即将生成4")
yield 4
print("即将生成5")
yield 5
print("生成器生成结束")
yield
#for x in myyield():
# print(x)
# 调用生成器函数来创建一个生成器,此生成器能生成 2,3,4,5
gen = myyield()
it = iter(gen) #用生成器拿到对应的迭代器
print(next(it)) #此时生成器函数才开始执行,并遇到yield停止 2
print(next(it)) #访问迭代器 3
print(next(it)) #4
print(next(it)) #5
print(next(it)) #生成器生成结束
生成器表达式:
语法:
把一个列表生成式的[ ]改成 (),就创建了一个generator:
(表达式 for 变量 in 可迭代对下哪个 [if 真值表达式])
作用:
用推导式形式创建一个新的生成器
说明:
if子句可以省略
gen = (x**2 for x in range(1,5))
it = iter(gen)
print(next(it)) #1
print(next(it))
print(next(it)) #9
print(next(it)) #16
print(next(it)) #StopInteration
生成器表达式和列表推导式的区别: 生成器表达式是现用现生成,列表推导式是一次生成静态数据
#列表推导式
l = [2,3,5,7]
l2 = [x ** 2 + 1 for x in l]
it = iter(l2)
print(next(it)) # 5
l[1] = 30
print(next(it)) # 10
#生成器表达式
l = [2,3,5,7]
gen = (x ** 2 + 1 for x in l)
it = iter(gen)
print(next(it)) #5
l[1] = 30
print(next(it)) #901