生成器使用总结: 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)函数使用
# return '在生成3之前用return返回' 将会发生异常 # 调用生成器函数来创建一个生成器,此生成器能生成 2,3,4,5 it = iter(gen) #用生成器拿到对应的迭代器 print(next(it)) #此时生成器函数才开始执行,并遇到yield停止 2
生成器表达式:
语法:
把一个列表生成式的[ ]改成 (),就创建了一个generator:
(表达式 for 变量 in 可迭代对下哪个 [if 真值表达式]) 作用: 用推导式形式创建一个新的生成器 说明: if子句可以省略
gen = (x**2 for x in range(1,5)) print(next(it)) #StopInteration
生成器表达式和列表推导式的区别: 生成器表达式是现用现生成,列表推导式是一次生成静态数据
l2 = [x ** 2 + 1 for x in l] gen = (x ** 2 + 1 for x in l)
|