Python生成器的详细介绍,首先生成器是Python初级开发者最难理解的概念之一,虽被认为是Python编程中的高级技能,但在各类项目中能够随处见到生成器的身影,你得不得去理解它、使用它、甚至爱上它。
提到生成器,总不可避免地要把迭代器拉出来对比着讲,生成器就是一个在行为上和迭代器很是相似的对象,若是把迭代器比做Android系统,那么生成器就是iOS,两者功能上差很少,可是生成器更优雅。
什么是迭代器
顾名思义,迭代器就是用于迭代操做(for循环)的对象,它像列表同样能够迭代获取其中的每个元素,任何实现了__next__方法(python2是next)的对象均可以称为迭代器。
它与列表的区别在于,构建迭代器的时候,不像列表把全部元素一次性加载到内存,而是以一种延迟计算(lazyevaluation)方式返回元素,这正是它的优势。好比列表含有中一千万个整数,须要占超过400M的内存,而迭代器只须要几十个字节的空间。由于它并无把全部元素装载到内存中,而是等到调用next方法时候才返回该元素(按需调用callbyneed的方式,本质上for循环就是不断地调用迭代器的next方法)。
以斐波那契数列为例来实现一个迭代器:
class Fib:
def __init__(self, n):
self.prev = 0
self.cur = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.n > 0:
value = self.cur
self.cur = self.cur + self.prev
self.prev = value
self.n -= 1
return value
else:
raise StopIteration()python
def __next__(self):
return self.next()
f = Fib(10)
print([i for i in f])编程
什么是生成器
知道迭代器以后,就能够正式进入生成器的话题了。普通函数用return返回一个值,和Java等其余语言是同样的,然而在Python中还有一种函数,用关键字yield来返回值,这种函数叫生成器函数,函数被调用时会返回一个生成器对象,生成器本质上仍是一个迭代器,也是用在迭代操做中,所以它有和迭代器同样的特性,惟一的区别在于实现方式上不同,后者更加简洁
最简单的生成器函数:函数
def func(n):
... yield n*2
...
func
<function func at 0x00000000029F6EB8>
g = func(5)
g
<generator object func at 0x0000000002908630>func就是一个生成器函数,调用该函数时返回对象就是生成器g,这个生成器对象的行为和迭代器是很是类似的,能够用在for循环等场景中。注意yield对应的值在函数被调用时不会马上返回,而是调用next方法时(本质上for循环也是调用next方法)才返回
g = func(5)
next(g)
10
g = func(5)
for i in g:
... print(i)
...
10
那为何要用生成器呢?显然,用生成器在逼格上要比迭代器高几个等级,它没有那么多冗长代码了,并且性能上同样的高效,为何不用呢?来看看用生成器实现斐波那契数列有多简单。
def fib(n):
prev, curr = 0, 1
while n > 0:
n -= 1
yield curr
prev, curr = curr, curr + prev
print([i for i in fib(10)])性能
生成器表达式
在前面一期「这样写代码更优雅」的文章里面曾经介绍过列表推导式(listcomprehension),生成器表达式与列表推导式长的很是像,可是它俩返回的对象不同,前者返回生成器对象,后者返回列表对象。lua
g = (x*2 for x in range(10)) type(g) <type 'generator'> l = [x*2 for x in range(10)] type(l) <type 'list'>