Python学习之路(15)——生成器

生成器可以说是Python语言中最吸引人的特性之一。

生成器也是一种迭代器,但是只能对其迭代一次。生成器作为一种特殊的迭代器,显得更加优雅,能够在很多情况下以一种优雅而又更低内存消耗的方式简化无界(无限)序列相关的操作。它不需要像迭代器那样,需要使用__ite__()和__next__()方法,只需要使用一个 yield 关键字。

大多数时候生成器是以函数来实现的,然而它并不返回一个值,而是yield一个值。

>>> def generator_function():
	for i in range(10):
		yield i

		
>>> for item in generator_function():
	print(item)

	
0
1
2
3
4
5
6
7
8
9
>>> 

  

上面是一个生成器函数的简单例子,但这种用法并不常用。生成器最佳应用场景是,不想在同一时间将所有计算出的大量结果集分配到内存中,特别是结果集里还包含循环。

比如下面一个计算斐波那契数列的生成器:

>>> def Fibs(n):
	a, b = 0, 1
	for i in range(n):
		yield b
		a, b = b, a + b

		
>>> for x in Fibs(10):
	print(x)

	
1
1
2
3
5
8
13
21
34
55
>>> 

  

再看一个例子,我们使用next()函数:

>>> def generator_function():
	for i in range(3):
		yield i

		
>>> gen = generator_function()
>>> print(next(gen))
0
>>> print(next(gen))
1
>>> print(next(gen))
2
>>> print(next(gen))
Traceback (most recent call last):
  File "<pyshell#131>", line 1, in <module>
    print(next(gen))
StopIteration

  

我们可以看到,在yield掉所有的值后,next()触发了一个StopInteration异常。这个异常告诉我们,所有的值都已经被yield完了。

 

生成器 vs 函数

生成器和函数的主要区别在于函数 return a value,生成器 yield a value,同时标记或者记忆 point of the yield 以便于在下次调用时从标记点恢复执行。 yield 使函数转换成生成器, 而生成器反过来又返回迭代器。

 

生成器表达式

生成器表达式是列表推导式的生成器版本,看起来像列表推导式,但是使用小括号“()”,而不是中括号“[]”,返回一个生成器对象,而不是列表对象。

>>> list1 = [x*x for x in range(10)]
>>> list1
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> 
>>> gen1 = (x*x for x in range(10))
>>> gen1
<generator object <genexpr> at 0x0000000003672258>
>>> 
>>> sum(list1)
285
>>> sum(gen1)
285
>>>

  

posted on 2018-03-01 20:07  nicolas_Z  阅读(156)  评论(1)    收藏  举报

导航