27 篇文章 0 订阅

# 如何生成斐波那契数列

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

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

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()

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

>>> for n in Fab(5):
...     print n
...
1
1
2
3
5

def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
# 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() 的值，不仅代码简洁，而且执行流程异常清晰。

>>> from inspect import isgeneratorfunction
>>> isgeneratorfunction(fab)
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

return 的作用

def read_file(fpath):
BLOCK_SIZE = 1024
with open(fpath, 'rb') as f:
while True:
if block:
yield block
else:
return

# send(msg) 与 next() 及返回值

def h():
print 'Wen Chuan',
m = yield 5  # Fighting!
print m
d = yield 12
print 'We are together!'
c = h()
c.next()  # 相当于c.send(None)
c.send('Fighting!')  # (yield 5)表达式被赋予了'Fighting!'

Wen Chuan Fighting!

send(msg) 和 next()是有返回值的，它们的返回值很特殊，返回的是下一个yield表达式的参数。比如yield 5，则返回 5 。到这里，是不是明白了一些什么东西？本文第一个例子中，通过for i in alist 遍历 Generator，其实是每次都调用了alist.Next()，而每次alist.Next()的返回值正是yield的参数，即我们开始认为被压进去的东东。我们再延续上面的例子：

def h():
print 'Wen Chuan',
m = yield 5  # Fighting!
print m
d = yield 12
print 'We are together!'
c = h()
m = c.next()  # m 获取了yield 5 的参数值 5
d = c.send('Fighting!')  # d 获取了yield 12 的参数值12
print 'We will never forget the date', m, '.', d

Wen Chuan Fighting!
We will never forget the date 5 . 12

# throw() 与 close()中断 Generator

def close(self):
try:
self.throw(GeneratorExit)
except (GeneratorExit, StopIteration):
pass
else:
raise RuntimeError("generator ignored GeneratorExit")
# Other exceptions are not caught

Traceback (most recent call last):
File "/home/evergreen/Codes/yield.py", line 14, in <module>
d = c.send('Fighting!')  #d 获取了yield 12 的参数值12
StopIteration

• 0
点赞
• 1
收藏
觉得还不错? 一键收藏
• 0
评论

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。