python 生成器和迭代器
一、迭代器
所谓的迭代器就能具有next方法的对象,调用next方法是,迭代器返回其下一个值,若没有值,则返回StopInteration异常,__iter__方法返回一个迭代器
注意:python 3.0中,迭代器实现的方法为__next__,而不是next
>>> class Fib:
def __init__(self):
self.a=0
self.b=1
def __iter__(self):
return self
def next(self):
self.a,self.b=self.b,self.a+self.b
if self.a>100:raise StopIteration
return self.a
>>> fib=Fib()
>>> fib.next()
1
>>> fib.next()
1
>>> fib.next()
2
>>> fib.next()
3
>>> fib.next()
5
>>> fib.next()
8
>>> fib.next()
Traceback (most recent call last):
File "<pyshell#177>", line 1, in <module>
fib.next()
File "<pyshell#169>", line 10, in next
if self.a>10:raise StopIteration
StopIteration
>>>
生成list,
>>> fib=Fib()
>>> list(fib)
<__main__.Fib instance at 0x00000000034603C8>
[1, 1, 2, 3, 5, 8]
>>> list(fib)
<__main__.Fib instance at 0x00000000034603C8>
[]
>>> fib=Fib()
>>> fib.next()
1
>>> list(fib)
<__main__.Fib instance at 0x00000000036075C8>
[1, 2, 3, 5, 8]
生成的list和当前迭代点有关,python提供内建函数iter,从可迭代对象获得迭代器
>>> alist='abcde'
>>> blist=[1,2,3,4]
>>> clist=('c','d','e')
>>> dlist={'a':1,'b':2}
>>> ita=iter(a)
>>> itb=iter(blist)
>>> ita=iter(alist)
>>> itc=iter(clist)
>>> itd=iter(dlist)
>>> itb.next()
1
>>> itc.next()
'c'
>>> ita.next()
'a'
>>> itd.next()
'a'
>>> itd.next()
'b'
字典迭代的为key
二、生成器
包含yield的语句的函数称为生成器,除了名字不同以外,和普通的函数也有很大的差异,这就在于它不像普通的函数返回值,而是每次产生一个断点,激活后就重那里开始
生成器由2部分组成,生成器函数和生成器的迭代器,前者是def定义包含yield语句的函数,后者为函数返回的部分
#!/usr/bin/env python
#-*- coding:utf-8 -*-
def yi(alist):
for sublist in alist:
for el in sublist:
print "before stop-point"
try:
yield el
except StopIteration:
print "itering is over"
print "after stop-point"
>>> import yie_test
>>> a=[[1,2],[3,4]]
>>> dir(yie_test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'yi']
>>> te=yie_test.yi(a)
>>> te.next
<method-wrapper 'next' of generator object at 0x7f3db05e8e10>
>>> te.next()
before stop-point
1
>>> te.next()
after stop-point
before stop-point
2
>>> te.next()
after stop-point
before stop-point
3
可以看出在每次执行的时候在yield语句处停住,可以通过type命令查看yi()类型为generator
生成器其他方法:
send:外部域访问生成器的方法,需要在内部挂起生成器,yield作为表达式使用而不是语句,换句话说当生成器重新运行的时候,返回外部通过send发送的值
def repeater(value):
while True:
new=(yield value)
if new is not None:
value=new
>>> import yie_test
>>> r=yie_test.repeater(10)
>>> r.next()
10
>>> r.next()
10
>>> r.next()
10
>>> r.send(11)
11
>>> r.next()
11
>>> r.next()
11
>>> r.next()
11
close方法用于停止生成器
throw方法用于在生成器内部引发一个异常。