zoukankan      html  css  js  c++  java
  • 【Python】生成器和迭代器

     

    l=[1,2,3,4]
     
    for n in l:
        print n

    在看上面这段代码的时候,我们没有显式的控制列表的偏移量,就可以自动的遍历了整个列表对象。那么for 语句是怎么来遍历列表l的呢?要回答这个问题,我们必须首先来看一下迭代器相关的知识。

    1. 迭代器

    迭代器对象要求支持迭代器协议,所谓支持迭代器协议就是对象包含__iter__()next()方法。其中__iter__()方法返回迭代器对象自己;next()方法返回下一个前进到下一个结果,在结尾时引发StopIteration异常。

    列表不是迭代器对象,但是列表通过__iter__()可以得到一个迭代器对象来遍历整个列表的内容,像列表这样的序列对象都属于这种情况;与序列不同,文件对象本身就是一种迭代器对象。

    l=[1,2,3,4]
    f=open('test.c','r')
     
    iter(l) == l
    Out[131]: False
     
    iter (f)== f
    Out[132]: True

    一个迭代器的例子:

    class Reverse:
        """Iterator for looping over a sequence backwards."""
        def __init__(self, data):
            self.data = data
            self.index = len(data)
        def __iter__(self):
            return self
        def next(self):
            if self.index == 0:
                raise StopIteration
            self.index = self.index - 1
            return self.data[self.index]

    2.生成器

    生成器使python可以很容易的支持迭代协议。生成器通过生成器函数产生,生成器函数可以通过常规的def语句来定义,但是不用return返回,而是用yeild一次返回一个结果,在每个结果之间挂起和继续它们的状态,来自动实现迭代协议。

    def reverse(data):
        for index in range(len(data)-1, -1, -1):
            yield data[index]

    3.for语句如何工作

    在我们最前面的遍历列表的for语句中,for使用了列表支持迭代器的性质,可以每次通过调用迭代器的next()方法,来遍历到列表中的值,直到遇到StopIteration的异常。

    4.迭代器、列表解析、生成器的分析比较

    • 迭代器(iterator)

      迭代器用来为类序列对象提供一个类序列的接口。迭代器就是生成一个有next()方法的对象,而不是通过索引来计数。

      序列、字典、文件中当使用for x in y的结构时,其实质就是迭代器,迭代器是和实际对象绑定在一起的,所以在使用迭代器时或者上述3者时不能修改可变对象的值。这会产生错误。如:在使用for x in y的结构来遍历字典时删除符合条件的字典内容,这会导致报错。

      创建迭代器的方法:iter(object)和iter(func,sentinel)两种。一种使用的是序列,另一种使用类来创建。

    • 列表解析(List comprehensions)

      主要用来动态的创建列表,和map()、filter()和reduce()一样可以用来产生列表。和生成器不同的是,列表解析一次生成一个列表,所占内存较大。

      列表解析的扩展版本语法:[expr for iter_var in iterable if cond_expr]

    • 生成器

      生成器是特定的函数,允许你返回一个值,然后“暂停”代码的执行,稍后恢复。生成器使用了“延迟计算”,所以在内存上面更加有效。

      生成器表达式:(expr for iter_var in iterable if cond_expr) 

      练习:使用文件读取,找出文件中最长的行的。最精简答案:max(len(x.strip()) for x in open('/etc/motd','r'))

  • 相关阅读:
    Redis开发与运维:SDS
    Redis开发与运维:数据迁移
    我的2019上半年
    C# 并发编程
    经典排序算法 — C# 版(上)
    图解 -- 树的汇总
    图解--队列、并发队列
    栈到CLR
    我们的数组
    算法复杂度
  • 原文地址:https://www.cnblogs.com/nju2014/p/4708498.html
Copyright © 2011-2022 走看看