首页 > 代码库 > Python学习笔记——迭代器和生成器

Python学习笔记——迭代器和生成器

1、手动遍历迭代器

  使用next函数,并捕获StopIteration异常。

def manual_iter():
    with open(./test.py) as f:
        try:
            while True:
                line = next(f)
                print line
        except StopIteration:
            pass

next函数也可以指定值来标记结尾

def manual_iter():
    with open(./test.py) as f:
        try:
            while True:
                line = next(f, None)
                if line == None:
                    break
                print line
        except StopIteration:
            pass

  使用for循环操作迭代器就不用考虑StopIteration异常,底层自动处理这些细节

2、代理迭代

使用iter来返回指定对象的迭代,iter(s)只是简单的通过调用 s.__iter__() 方法来返回对应的迭代器对象

class Node:
    def __init__(self, value):
        self._value = value
        self._children = []

    def __repr__(self):
        return Node({!r}).format(self._value)

    def add_child(self, node):
        self._children.append(node)

    def __iter__(self):
        return iter(self._children)

node1 = Node(1)
node2 = Node(2)
root = Node(root)
root.add_child(node1)
root.add_child(node2)

i = iter(root)
print next(i)
print next(i)

for n in root:
print n
 

  需要注意的是,实现了__iter__()可以使用for循环,但是不能直接使用next()进行调用,要想使用next,必须先调用root.iter()

 

3、实现迭代器协议

 Python的迭代协议要求一个 __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了next 方法,注意python3中是__next__方法。并通过 StopIteration 异常标识迭代的完成。最简单的方式就是代理迭代中使用的方式。还有一种方式就是__iter__()返回对象本身,该对象实现next()方法。

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def next_(self): # 在python3中,为__next__()
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration()
        return self.a # 返回下一个值

 

4、反向迭代

  使用内置的reversed可以实现反向迭代,前提是对象大小可以确定,或者实现了__reversed__方法。

a = [1, 2, 3, 4]
for x in reversed(a):
    print x

  使用__reversed__方法

class Countdown:
    def __init__(self, start):
        self.start = start

    # Forward iterator
    def __iter__(self):
        n = self.start
        while n > 0:
            yield n
            n -= 1

    # Reverse iterator
    def __reversed__(self):
        n = 1
        while n <= self.start:
            yield n
            n += 1

for rr in reversed(Countdown(30)):
    print rr
for rr in Countdown(30):
    print rr

 

5、迭代器切片

  对迭代器进行切片操作,可以使用itertools.islice()方法来实现,函数 islice() 返回一个可以生成指定元素的迭代器,它通过遍历并丢弃直到切片开始索引位置的所有元素。 然后才开始一个个的返回元素,并直到切片结束索引位置。

 

def count(n):
    while True:
        yield n
        n += 1
c = count(10)
import itertools
for x in itertools.islice(c, 10, 20):
    print x

 

Python学习笔记——迭代器和生成器