• 如果您觉得本站非常有看点，那么赶紧使用Ctrl+D 收藏吧

# Python中yield简单用法

1个月前 (10-30) 15次浏览

# Python中yield简单用法

## 生成Fibonacci数列

Fibonacci数列是一个经典递归数列，第0个数为0，第1个数为1，除第0个和第1个数外，任意一个数都可由前两个数相加得到。

### Fibonacci数列（版本一）

``````def fab(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1
fab(5)
``````

``````1
1
2
3
5
``````

### Fibonacci数列（版本二）

``````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
``````

``````1
1
2
3
5
``````

``````for i in range(1000): pass
``````

``````for i in xrange(1000): pass
``````

### Fibonacci数列（版本三）

``````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 n in Fab(5):
print n

``````

Fab类通过next()不断返回数列的下一个数，内存占用始终为常数：

``````1
1
2
3
5
``````

### Fibonacci数列（版本四）（yield）

``````def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b      # 使用 yield
# print b
a, b = b, a + b
n = n + 1

for n in fab(5):
print n
``````

``````1
1
2
3
5
``````

``````>>>f = fab(5)
>>> f.next()
1
>>> f.next()
1
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
>>> f.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
``````

### 小结

yield的好处是显而易见的，把一个函数改写为一个generator就获得了迭代能力，比起用类的实例保存状态来计算下一个next()的值，不仅代码简洁，而且执行流程异常清晰。

## 特殊的generator函数其他相关

``````>>>import types
>>> isinstance(fab, types.GeneratorType)
False
>>> isinstance(fab(5), types.GeneratorType)
True
``````

``````>>>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
``````

``````>>>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
``````

## 另一个例子——用在文件读取的yield

``````def read_file(fpath):
BLOCK_SIZE = 1024
with open(fpath, 'rb') as f:
while True: