【微语】不要争论所谓的小事,即使赢了也得不到好处。
生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器。
既然生成器这么NB,那我们先说说列表生成式。
列表生成式
列表的生成方式有下面三种: (1)、用[]定义,比如a = [1,2,3,4]; (2)、用list()方法生成,比如a = list((1,2,3,4)); (3)、用列表生成式 我们来看看列表生成式的基本语法:
[exp for iter_var in iterable]
其工作过程如下: (1)、迭代iterable中的每个元素; (2)、每次迭代都先把结果赋值给iter_var,然后通过exp得到一个新的计算值; (3)、最后把所有通过exp得到的计算值以一个新列表的形式返回。 其过程相当于下面这种语法:
L = []
for iter_var in iterable:
L.append(exp)
带过滤功能的列表生成式的基本语法:
[exp for iter_var in iterable if_exp]
其工作过程如下: (1)、迭代iterable中的每个元素,每次迭代都先判断ifexp表达式结果为真,如果为真则进行下一步,如果为假则进行下一次迭代; (2)、把迭代结果赋值给itervar,然后通过exp得到一个新的计算值; (3)、最后把所有通过exp得到的计算值以一个新列表的形式返回; 其过程相当于下面这个例子:
L = []
for iter_var in iterable:
if_exp:
L.append(exp)
循环嵌套的列表生成式的格式:
[exp for iter_var_A in iterable_A for iter_var_B in iterable_B]
其工作过程是每迭代iterableA中的一个元素,就把ierableB中的所有元素都迭代一遍。 相当于下面这种写法:
L = []
for iter_var_A in iterable_A:
for iter_var_B in iterable_B:
L.append(exp)
通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。这时候生成器在这里就发挥作用了。
生成器
在python中使用yield的函数称为生成器。如下:
def count(n):
while n > 0:
yield n
n -= 1
跟普通函数不同的是生成器返回的是一个迭代器函数,只能用于迭代操作,可以说生成器就是一个迭代器。在调用生成器运行的过程中,每次运行到yield会暂停并保存所有的运行信息并返回yield的值,在下次调用next()方法的时候当前的位置继续运行。 例如:
# 用普通函数创建斐波拉契函数
>>> def fib1(n):
... a, b, count = 0, 1, 0
... while count < n:
... print(a)
... a, b = b, a+b
... count += 1
...
>>> fib1(10)
0
1
1
2
3
5
8
13
21
34
>>>
# 用生成器创建
>>> def fib2(n):
... a,b,count = 0,1,0
... while count<n:
... yield a
... a,b=b,a+b
... count += 1
...
>>> for i in fib2(10):
... print(i)
...
0
1
1
2
3
5
8
13
21
34
作为生成器,因为每次迭代就会返回一个值,所以不能显示的在生成器函数中return 某个值,包括None值也不行,否则会抛出“SyntaxError”的异常,但是在函数中可以出现单独的return,表示结束该语句。 通过固定长度的缓冲区不断读文件,防止一次性读取出现内存溢出的例子:
def read_file(path):
size = 1024
with open(path,'r') as f:
while True:
block = f.read(SIZE)
if block:
yield block
else:
return
从上可以看出生成器的优点了吗?