list1 = [n*2 for n in range(10)]
产生的是一个列表,非生成器
gen = (n*2 for n in range(10))
产生的是生成器:
不会保存成一个列表,只会保存当前值+一个迭代算法
比如果这里的迭代算法是 按照n的循环变量,在range(10)里面取数*2即可
如下是一个普通的含循环函数
def fib1(n):
#打印斐波拉契数列
i,a,b = 0,0,1
while(i<n):
print(b)
a,b = b,a+b#相当于(a,b) = (b,a+b)右边都是a,b原始的值,而不是先a = b,在b = a+b
i+=1
fib1(10)
这中函数的特征是,在调用时,一定要等调用结束后才能执行之后的代码。也就是这里的fib1(10)调用,函数内整个循环走完,才能执行力fib1(10)之后的代码。
如下是一个生成器函数
def fib2(n):
#设计一个斐波拉契数列生成器
i,a,b = 0,0,1
while(i<n):
yield b#保存当前b的信息,这里是一个循环的出入口
a,b = b,a+b
i+=1
return 'done'
f = fib2(10)
print(f.__next__())#单次迭代
print(f.__next__())
for it in f:#会接着单次迭代后,继续迭代,而不是重新迭代
print(it)
此处的
f = fib2(10)
是返回的一个迭代器。此时fib2(n)就是一个生成器函数,其返回值并不是'done',而是返回一个生成器命名为f
可以看到,我们在
print(f.__next__())#单次迭代
就已经输出了斐波拉契数列的第一个值,但是输出之后,我们还可以执行其他的代码,而此时的迭代器f相当于暂停状态。只有再次执行迭代,才会生成新的值。可以说,迭代器是一种迭代一次,生成一个值存储到yield。而不是先生成一系列的值,然后依次往后移动。迭代器只有保存当前的值,其存储到yield里面。
注意:
当迭代器函数的返回值是一个迭代器,而这个函数中的return 语句是返回一个异常信息,比如上面函数的
return 'done'
所以为了保证出现异常(也就是迭代到最后一个值时,还在执行迭代),我们需要进行异常检查
try:
print(f.__next__())
except StopIteration as e:
print('迭代完毕,不可继续迭代')
这样,当出现异常时,就不会因为异常而中断程序。而而只是会抛出一个异常信息而已。
本文到此结束,关于生成器函数的并发,我会再下一个文档发表。