对于调用一个普通的Python函数,一般是从函数的第一行代码开始执行,结束于return语句、异常或者函数所有语句执行完毕。一旦函数将控制权交还给调用者,就意味着全部结束。函数中做的所有工作以及保存在局部变量中的数据都将丢失。再次调用这个函数时,一切都将从头创建。Python是通过生成器来实现类似于协同程序的概念:生成器可以暂时挂起函数,并保留函数的局部变量等数据,然后在再次调用它的时候,从上次暂停的位置继续执行下去。
提高你的 Python:解释 yield 和 Generators(生成器)
>>> a = [i for i in range(100) if not(i%2) and i%3] >>> a [2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98] >>> b = {i:i % 2 == 0 for i in range(10)} >>> b {0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False} >>> c = {i for i in [2,1,1,1,5,6,9,0,3,4,5,5,7,6,8,3]} >>> c {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> d = "i for i in 'I love fishc.com'" >>> d "i for i in 'I love fishc.com'" >>> e = (i for i in range(10)) >>> e <generator object <genexpr> at 0x0000000002F08AF8> >>> next(e) 0 >>> next(e) 1 >>> next(e) 2 >>> next(e) 3 >>> for each in e: print(each) 4 5 6 7 8 9 >>> sum(i for i in range(100)) 4950
以上是列表推导式,其实还有字典推导式,而没有元组推导式,元组推导式的结果其实是一个生成器,如上例的e。
def fibs(): a = 0 b = 1 while True: a, b = b, a + b yield a >>> for each in fibs(): if each > 100: break print(each, end=' ') 1 1 2 3 5 8 13 21 34 55 89
上面的代码就是通过生成器来实现的斐波拉契数列。生成器是遇到yield关键字时,函数就可以暂时挂起的,只有当重新访问生成器的时候,函数又会从生成器的上次的地方继续执行。