Iterator
在python中我们常用到for语句,比较常见的有如:
for x in rang(5):
print x,
返回的结果如下:
0 1 2 3 4
for语句可以使用的场景往往不仅仅局限于list中,还可以用到其他的地方,比如在Dict和一些字符串中间都可以遍历:
# iterate through dict
pc={"name":"mypc", "port": 80}
for key in pc:
print key,
# result
'name' 'port'
# iterate through string
s = "You!"
for c in s:
print c,
# result
Y o u !
和很多静态编译语言,如java的思想类似,我们需要能够遍历一个对象,那么这个对象应该遵守某种规则,使得它可被遍历。在java中间是通过iterator pattern的手法,实现iterable接口。python中间要能够遍历一个对象,那么这个对象就必须是iterable的。只是不需要专门实现一个接口。
Iteration协议:
前面说到,既然我们要能够迭代访问某个对象,需要对象是iterable的。那么我们先看看一个可以迭代对象表现的特征:
items = [1, 2, 3]
it = iter(items)
it.next()
1
it.next()
2
it.next()
3
it.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
和java中的for循环类似,python中当对一个对象进行for循环的时候,比如如下的代码:
for x in obj:
# statements
底层对应生成的的代码形式如下:
_iter_ = obj.__iter__()
while 1:
try:
x = _iter.next()
except StopIteration:
break
# statements
我们从前面遍历一个数组的过程中可以看到,终止一个循环的条件是StopIteration的异常。
实现Iteration协议:
现在,假定我们自己要定义一个可以遍历的对象,那么按照前面讨论的协议过程,代码需要实现两个方法,一个是__iter__,一个是next。比如我们有如下的代码:
class CountDown:
def __init__(self, start):
self.count = start
def __iter__(self):
return self
def next(self):
if self.count <= 0:
raise StopIteration
r = self.count
self.count -= 1
return r
这是一个典型的实现iteration协议的代码。主要从指定的一个数字倒序返回到0.我们遍历这个对象的代码如下:
for x in CountDown(5):
print x,
#result
5 4 3 2 1
总结:
从整个过程看来,使得一个对象可以被遍历无非就是自己定义实现__iter__和next两个方法。
__iter__方法返回一个iterator,类似于java中间实现iterable接口而需要返回一个Iterator。而next方法则是返回具体下一个元素。当把两个方法放在一个类里头的时候,相当于把实现两个接口的东西糅合在一起了。Python里面没有专门接口的定义,这样拼凑过来就可以了。当然,在实际情况下也可以将两者拆分,像java中间那样,类似于两个专职的功能的类。比如说前面示例,拆开了写的形式如下:
class countdown(object):
def __init__(self, start):
self.count = start
def __iter__(self):
return countdown_iter(self.count)
class countdown_iter(object):
def __init__(self, count):
self.count = count
def next(self):
if self.count <= 0:
raise StopIteration
r = self.count
self.count -= 1
return r