一 iterator迭代器
1) 迭代器是实现了迭代器协议的某种类型,一般需要实现如下两个方法
(1)在python2.x中,next方法,在python3.x中,为__next__(),返回容器的下一个元素
(2)__iter__方法,返回迭代器自身
通常的iterator与for关键字配合使用,for语句在容器对象中调用__iter__()函数返回一个定义了next()或__next__()方法的iterator。通过iterator的next()或__next__()方法来在容器中逐一访问元素,没有后续元素,next()或__next__()就会抛出一个异常,告知for循环结束。
2)iterator的使用
def
TestIterator():
for
e
in
[
2
,
4
,
8
,
16
] :
print
(e)
for
c
in
'
ABCDEFG
'
:
print
(c)
#
use list iterator
for
line
in
open(
"
test.txt
"
).readlines():
print
(line )
#
use file iterator, and it is better. not read all data into memory
for
line
in
open(
"
test.txt
"
):
print
(line )
#
TestIterator()
3) 自定义iterator类型
python2.7 实例:
class
MyIterator():
def
__init__
(self, step):
self.step
=
step
def
next(self):
if
self.step
==
0:
raise
StopIteration
self.step
-=
1
return
self.step
def
__iter__
(self):
return
self
myI
=
MyIterator(
4
)
for
e
in
myI:
print
e
在python2.7下运行正常,但是在3.1下有next需要改为__next__,有错误如下:TypeError: iter() returned non-iterator of type 'MyIterator'
python3.1代码如下:
class
MyIterator():
def
__init__
(self, step):
self.step
=
step
def
__next__
(self):
if
self.step
==
0:
raise
StopIteration
self.step
-=
1
return
self.step
def
__iter__
(self):
return
self
myI
=
MyIterator(
4
)
for
e
in
myI:
print
(e)
二 generator
1. 有yield关键字的函数则会被识别为generator函数,此时其实函数返回的仍然是iterator。
2. generator函数用来生成一个序列,但不是一次完成,而是经过多次调用:调用generator函数得到一个generator的对象。之后每次调用generator的next()或__next__()方法都会得到序列的下一个值。
3. 如何做到的?
generator的next()或__next__()导致generator函数被调用,遇到yield,返回序列一个值,然后generator函数挂起。下一个next()或__next__()让generator函数恢复,从挂起处往后继续执行。
这样做的好处之一是不必一次生成序列所有元素(例如序列很长时,存所有元素并不好),而是像有一个iterator一样一个个生成。
1)实例
def
TestGenerator(l):
for
e
in
l:
print
(
"
before yield:
"
+
str(e))
yield
e
print
(
"
after yield:
"
+
str(e))
for
el
in
TestGenerator([
6
,
7
,
8
,
9
]):
print
(el)
#
break
运行结果如下:
before yield:6
6
after yield:6
before yield:7
7
after yield:7
before yield:8
8
after yield:8
before yield:9
9
after yield:9
2)实例
def
Generator2(l):
for
e
in
l:
print
(
"
before yield:
"
+
str(e))
enew
=
yield
e
print
(
"
after yield:
"
+
str(enew))
def TestGenerator2():
it
=
Generator2([
6
,
7
,
8
,
9
])
for
i
in
range(
6
,
10
):
if
i
==
8
:
element
=
it.send(
800
)
else
:
element
=
it.next()
print
(element)
在python2.7下运行正常,但是在3.1下需要next()改为__next__(),否则有错误如下:AttributeError: 'generator' object has no attribute 'next'
运行结果:
before yield:6
6
after yield:None
before yield:7
7
after yield:800
before yield:8
8
after yield:None
before yield:9
9
3)实例
def
counter(maximum):
i
=
0
while
i
<
maximum:
val
=
(
yield
i)
#
If value provided, change counter
if
val
is
not
None:
i
=
val
else
:
i
+=
1
def
TestCounter():
co
=
counter(
10
)
for
e
in
co:
print
(e)
if
(e
==
2
):
co.send(
8
)
TestCounter()
运行结果:
0
1
2
9
4)next()或__next__()和send()方法作用大致是相同,next()或__next__()相当于send(None)。
参考:
http://www.lfyzjck.com/2010-10-23/360.html
http://www.tech126.com/python-yileld/
http://lukejin.javaeye.com/blog/587051
http://www.i7xh.com/2009/10/22/py_iter/
http://blog.csdn.net/chszs/archive/2009/01/24/3852669.aspx
http://hi.baidu.com/uestcfb/blog/item/4f138fd314ed26043bf3cfd3.html
完!