2014-3-4迭代器必须在类中实现,因为要实现 next, __iter__ 方法
一般在next里满足的停止迭代条件后要使用 raise StopIteration 来结束迭代,当然了,自定义异常抛出也行.
http://hi.baidu.com/rails7/item/5b033a437a8f75d2c0a59241
迭代器(对象)版本
#!/usr/bin/env python # -*- coding: utf-8 -*- class Fib(object): a = 0 b = 1 def next(self): self.a, self.b = self.b, self.a + self.b # 超过10000后停止迭代 if self.a > 10000: raise StopIteration return self.a def __iter__(self): return self fibs = Fib() for f in fibs: print f
生成器(函数)版本
#!/usr/bin/env python # -*- coding: utf-8 -*- def fib(): a, b = 0, 1 while True: a, b = b, a+b if a > 1000 and a < 5000: yield "1000 to 5000 don`t display" continue if a > 10000: raise StopIteration yield a for f in fib(): print f
---------------------------
关于yield表达式(generator) 疑惑了很久, 昨晚坐公交翻看了 Manuals总结如下:
例子党, 直接上代码..
# -*- coding: utf-8 -*- """例子1 一个函数含有yield表达式 这个函数就不是普通函数,而是生成器(generator) """ def gen(): print "start" #*0 m = yield 2 #*1 # yield意思是产生, 此表示产生2 就是调用可以返回2 (当然,返回是有条件的) print m #*2 n = yield 3 #*3 print n #*4 try: #*5 print "end" #*6 except StopIteration as e: #*7 print e #*8 # raise e # 先说明yield表达式, yield有点像<前置操作符>, 跟在表达式前面,用于把表达式的值返回给调用者, (yield 2)本身的值赋给m g = gen() """ result: <generator object f at 0x01228EE0> """ #↑>>> 可以看出是一个generator, 此时并没有执行 *0和*1行 g.send(3) """ result: TypeError: can't send non-None value to a just-started generator """ #↑>>> 开始生成器不能send非空值 g.send(None) # 住: g.next()相当于g.send(None) 本人习惯用send而不是next """ result: start 2 #此时函数(生成器)返回了2(就是yield后的,此时你可以理解为yield相当于return,但是返回后暂停了执行) """ # 此时函数挂起(让出cpu使用权)并保持状态,直到遇到下一个next/send # g.send(None) 调用者把None这个消息send给上一个yield表达式,由于第一次调用,没有上一个yield. # 到目前为止, 调用了一次send(None) 总结一下, 上面说到保持状态:目前函数运行到*1行并挂起 print g.send(5) """ result: 5 3 #和上面一样,第二个yield生成(返回)的值为3 """ # 此时函数从*1行后继续执行 通过调用g.send(5),调用者把5这个消息send给上一个yield表达式(yield 2) 既:(yield 2)这个整体的值,此时m = 5 # 到目前为止, 调用了一次send(None),一次send(5) 总结一下, 上面说到保持状态:1.此时的状态是:m(既yield 2这个整体的结果值)被调用者发送消息赋值为5 2.目前函数运行到*3行并挂起 print g.send(6) #result: # 6 # end # StopIteration # 此时函数从*3行后继续执行 通过调用g.send(6),调用者把6这个消息send给了上一个yield表达式(yield 3) 既:(yield 3)这个整体的值,此时n = 6 # 继续往下执行,由于没有了遇不到yield,所有会出现 StopIteration 异常而结束 # 到目前为止,生成器函数运行结束,由于生成器会记住状态, 再调用send/next还会出现StopIteration异常 # 通过生成器, 调用者和函数内部可以交互消息, 暂停执行, 可用同步代码处理异步, 如:tornado的 @gen修饰器, twisted的@inlineCallback修饰器... """例子2 在for循环迭代过程中, 系统自动回调用next方法,不用显示调用 """ def foo(list2gen): for item in list2gen: yield item # 此时 yield有点像调用一次而不结束而是暂停执行的return ,这里的好处类似iterator, 要给你生成给你一个,而不是像list, 一下都给你,占用内存大 l = [2,3,4] for i in foo(l): # 这里foo把l变成了生成器 print i # result: # 2 # 3 # 4 """例子3 一个模拟无穷列表的情况(此处必须用生成器) """ def g(): n = 0 while True: yield n n += 1 # 哈哈,无限生成 递增数, 一直打印, 直到(内存耗尽?) for i in g(): print i