`
frank-liu
  • 浏览: 1665629 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

python中的iterator

阅读更多

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
 

参考链接:

http://www.slideshare.net/dabeaz/python-generator-hacking

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics