• 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
  • 相关阅读:
    UUID是否会重复、UUID的生成原理
    自己动手实现一个UUID
    分布式系统唯一ID生成方案
    docker命令中的启动停止命令的使用
    执行git push出现"Everything up-to-date"
    Github提交错误:Invalid username or password. fatal: Authentication failed for
    Allure安装
    git clone 时候出现Please make sure you have the correct access rights and the repository exists.问题解决
    使用fiddler,har2case 将api参数转成yaml格式
    Fiddler怎么可以抓取https的请求包
  • 原文地址:https://www.cnblogs.com/lilinwei340/p/6819032.html
Copyright © 2020-2023  润新知