本文代码较多,建议阅读时间5分钟,并且注重理论与实践相结合
原文选自菜鸟教程可以点击阅读原文
举个栗子:斐波那契数列
斐波那契数列是一个简单的递归数列,除了第一个第二个外,其他都可由任意两个数组成。
Eg1.简单输出前N个数:
def fab(max):
n,a,b = 0,0,1
while n < max:
print(b)
a ,b = b ,a+b
n = n+1
fab(5)
Eg2.使用列表(提高函数的复用性):
def fab(max):
n , a , b = 0,0,1
L = []
while n<max:
L.append(b)
a,b = b,a+b
n = n+1
return L
for n in fab(5):
print(n)
Eg3.支持iterator的class类:
class Fab(object):
def __init__(self,max):
self.max = max
self.n,self.a,self.b = 0,0,1
def __iter__(self):
return self
def __next__(self):
if self.n<self.max:
r = self.b
self.a ,self.b = self.b ,self.a+self.b
self.n = self.n+1
return r
raise StopIteration
for i in Fab(5):
print(i)
Eg4.主角yield:
def fab(max):
n,a,b = 0,0,1
while n<max:
yield b
a,b = b,a+b
n = n+1
for i in fab(5):
print(i)
打印输出:
1
1
2
3
5
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
fab的工作流程:
>>> f = fab(5)
>>> f.next()#Python2的写法
Traceback (most recent call last):
File "<pyshell#101>", line 1, in <module>
f.next()
AttributeError: 'generator' object has no attribute 'next'
>>> f.__next__()#Python3的写法
1
>>> f.__next__()
1
>>> f.__next__()
2
>>> f.__next__()
3
>>> f.__next__()
5
>>> f.__next__()
Traceback (most recent call last):
File "<pyshell#107>", line 1, in <module>
f.__next__()
StopIteration
Eg5.判断fab是否是一个特殊的generator函数?
>>> from inspect import isgeneratorfunction as isg
>>> isg(fab)
True
Eg6.类的定义与实例
>>> import types
>>> isinstance(fab,types.GeneratorType)
False
>>> isinstance(fab(5),types.GeneratorType)
True
证明了fab是无法迭代的,fab(5)可以
>>> from collections import Iterable
>>> isinstance(fab,Iterable)
False
>>> isinstance(fab(5),Iterable)
True
Eg7.每次调用fab函数都会生成一个新的generator,各实例互不影响:
>>> f1 = fab(3)
>>> f2 = fab(5)
>>> print('f1:',f1.__next__())
f1: 1
>>> print('f2:',f2.__next__())
f2: 1
>>> print('f1:',f1.__next__())
f1: 1
>>> print('f2:',f2.__next__())
f2: 1
>>> print('f1:',f1.__next__())
f1: 2
>>> print('f2:',f2.__next__())
f2: 2
>>> print('f2:',f2.__next__())
f2: 3
>>> print('f2:',f2.__next__())
f2: 5
http://www.runoob.com/w3cnote/python-yield-used-analysis.html