生成器就是一个带yield的函数(只要函数包含yield,函数调用就会返回一个生成器对象),普通的函数只能返回一次,但一个生成器可以暂停执行并返回一个中间的结果,当生成器的next()方法被调用的时候,会从离开的地方继续执行,而且可以上次调用的全部局部变量保持不变。说得直白点,生成器就是一个特殊的函数,它能产生一列的结果而不仅是产生单一结果。
生成器也是一个迭代器,拥有next方法而且行为与迭代器彻底相同,可用于for循环中(for循环每次自动调用next方法直到抛出StopIteration异常
),而且定义一个生成器比定义一个迭代器简单不少。html
生成器能够看做是一个迭代器,拥有next()方法,当一个真正的返回(调用return)或者函数结束没有更多的值返回时(调用next()),会抛出StopIteration异常
python
用生成器实现斐波那契系数编程
def fab(max): a = 1 b = 1 i = 0 while i<max: yield b a,b = b,a+b i += 1 it = fab(5) for i in range(7): print it.next() # 1 # 2 # 3 # 5 # 8 # Traceback (most recent call last): # File "test.py", line 13, in <module> # print it.next() # StopIteration
1.当第1次调用生成器函数的时候,并不运行函数(如函数中有print语句,并不执行),**只是构建生成器对象*,并将生成器返回**,生成器函数可带参数也可不带参数闭包
>>> def fab(max): ... a,b,i = 1,1,0 ... while i<max: ... yield b ... a,b = b,a+b ... i +=1 ... >>> f = fab(10) >>> type(f) <type 'generator'>
2.当第1次调用生成器的next方法时,生成器才开始执行生成器函数(并非构建,此时运行1中说的print语句),直到遇到yield暂停执行,并将yield的参数做为这次next的返回值。并发
>>> f.next() 1
3.以后每次调用next方法,生成器将恢复环境并从上次运行的地方开始从新开始执行,直到再次遇到yield时暂停,而且将yield的参数做为next的返回值。app
>>> f.next() 2
4.当调用next方法时生成器结束(遇到空的return语句或到达函数末尾),这次next将会抛出StopIteration异常
5.生成器函数中不容许有参数的return语句,若是出现,将会抛出SyntaxError: 'return' with argument inside generator
错误ide
def fab(max): a = 1 b = 1 while i<max: yield b a,b = b,a+b i += 1 return False it = fab(5) # File "test.py", line 8 # return False # SyntaxError: 'return' with argument inside generator
6.生成器函数在每次暂停执行时,函数体内的全部变量都将被封存(freeze)在生成器中,并将在恢复执行时还原,而且相似于闭包,即便是同一个生成器函数返回的生成器,封存的变量也是互相独立的。函数式编程
send():将值返回给生成器
throw():在生成器中抛出异常
close():要求生成器退出函数
send是除了next方法之外另外一个恢复生成器的方法;此时,yield必须是一个表达式,yield表达式返回的值就是调用send方法的参数,生成器从yield开始运行,直到再次遇到yield,并将yield的参数做为send方法的返回值.net
def gener(): name = 'not input' while True: name = yield name if name == None: name = "not input" else: name = "I'm " + name it = gener() print it.send(None) print it.send("zhainankl") print it.next() # not input # I'm zhainankl # not input
这个方法用于关闭生成器。对关闭的生成器后再次调用next或send将抛出StopIteration异常。
这个方法用于在生成器内部(生成器的当前挂起处,或未启动时在定义处)抛出一个异常。
def thread1(): for x in range(4): yield x def thread2(): for x in range(4,8): yield x threads=[] threads.append(thread1()) threads.append(thread2()) def run(threads): #写这个函数,模拟线程并发 pass run(threads)
def run(threads): for t in threads: try: print t.next() except StopIteration: pass else: threads.append(t)