generator
生成器generator:一边循环一边计算的机制。
生成器是一个特殊的程序,可以被用于控制循环的迭代行为。python中的生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,可以使用next()函数和send()函数恢复生成器。
生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用。但是,不同于一般函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这个消耗的内存数量将大大减小。因此,生成器看起来像是一个函数,但是表现得像迭代器。
创建generator
方法一:生成器表达式
生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果。
只要把一个列表生成式中的[]改为(),就创建一个generator。
>>> list(x*x for x in range(5))
[0, 1, 4, 9, 16]
>>> list[x*x for x in range(5)]
File "<stdin>", line 1
list[x*x for x in range(5)]
^
SyntaxError: invalid syntax
>>> #列表解析生成列表
... [ x**3 for x in range(5)]
[0, 1, 8, 27, 64]
>>> #生成器表达式
... ( x**3 for x in range(5))
<generator object <genexpr> at 0x105d8ba50>
>>> list( x**3 for x in range(5))
[0, 1, 8, 27, 64]
方法二:生成器函数
也是用def定义,如果一个函数至少包含一个yield声明(当然它也可以包含其他yield或return),那么它就是一个generator.
yield和return都会让函数返回一些东西,区别在于,return声明彻底结束一个函数,而yield声明是暂停函数,保存它的所有状态,并且后续被调用后会继续执行。
>> def my_gen():
... n=1
... print "first"
... yield n
... n+=1
... print "second"
... yield n
...
>>> for item in my_gen():
... print item
...
first
1
second
2
>>
一个迭代可以被写成生成器函数,也可以被写成生成器表达式,均支持自动和手动迭代。而且这些生成器只支持一个active迭代,也就是生成器的迭代器就是生成器本身。
迭代器(迭代就是循环)
可以直接作用于for循环的数据类型:
- 集合数据类型,如list、tuple、dict、set、str
- generator,包括生成器函数和表达式?
- 这些可以直接作用于for循环对象的统称为可迭代对象:Iterable
- 可以被next()函数调用并不断返回下一个值的对象成为迭代器:Iterator
- 生成器都是Iterator对象,但list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器)。
- 把list、dict、str等Iterable变成Iterator可以使用iter()函数。
Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
小结
- 凡是可作用于for循环的对象都是Iterable类型;
- 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
- 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。