在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的。只是不需要专门实现一个接口。
前面说到,既然我们要能够迭代访问某个对象,需要对象是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的异常。
现在,假定我们自己要定义一个可以遍历的对象,那么按照前面讨论的协议过程,代码需要实现两个方法,一个是__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