python学习笔记之八:迭代器和生成器

一. 迭代器python

在前面的笔记中,已经提到过迭代器(和可迭代),这里会对此进行深刻讨论。只讨论一个特殊方法---__iter__,这个方法是迭代器规则的基础。函数

1.1 迭代器规则spa

      迭代的意思是重复作一些事情不少次,到如今为止只是在for循环中对序列和字典进行迭代,但实际上也能对其余的对象进行迭代:实现__iter__方法的对象。code

      __iter__方法返回一个迭代器,所谓迭代器就是具备next方法(这个方法在调用时不须要任何参数)的对象。在调用next方法时,迭代器会返回它的下一个值。若是next方法被调用,但迭代器没有值能够返回,就会引起一个StopIteration异常。对象

      为何不用列表?列表是一次性获取全部值的,若是有不少值,列表会占用太多的内存,可是迭代器能够在使用时计算一个值时获取一个值,使用迭代器更通用,简单,优雅。blog

      下面来看一个不使用列表的例子:教程

__metaclass__ = type
 
class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 0
    def next(self):
        self.a,self.b = self.b,self.a + self.b
        return self.a
    def __iter__(self):
        return self

注意:迭代器实现了__iter__方法,这个方法实际上返回迭代器自己。不少状况下,__iter__会放到其余的会在for循环中使用的对象中。这样一来,程序就能返回所需的迭代器。此外,推荐使用迭代器实现它本身的_iter__方法,而后就能直接在for循环中使用迭代其自己了。递归

>>> f = Fibs()
>>> for n in f:
    if n > 10:
        print n
        break

13

 

1.2 从迭代器获得序列内存

除了在迭代器和可迭代对象上进行迭代外,还能把它们转换为序列。在大部分能使用序列的状况下,能使用迭代器替换。关于这个的一个颇有用的例子是使用list构造方法显式地将迭代器转化为列表。element

__metaclass__ = type
 
class TestIterator:
    value = 0
    def next(self):
        self.value += 1
        if self.value > 10:raise StopIteration
        return self.value
    def __iter__(self):
        return self
>>> ti = TestIterator()
>>> list(ti)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

 二. 生成器

      生成器是python新引入的概念,因为历史缘由,它也叫简单生成器。它和迭代器多是近几年来引入的最强大的两个特性。生成器能够帮助读者写出很是优雅的代码。

      生成器是一种用普通的函数语法定义的迭代器。让咱们先看看怎么建立和使用生成器,而后再了解一下她的内部机制。

2.1 建立生成器

首先建立一个展开嵌套列表的函数,参数是一个列表的列表,相似于nested = [[1,2],[3,4],[5]],函数按照顺序打印出列表中的数字:

__metaclass__ = type
 
def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element

      这个函数首先迭代提供的嵌套列表中的全部子列表,而后按顺序迭代列表中的元素。yield语句是新知识,任何包含yield语句的函数都称为生成器。它不像return那样返回值,而是每次产生多个值。每次产生一个值,函数就会被冻结:即函数停在那点等待被激活,函数被激活后就从中止的那点开始执行。

接下来能够经过在生成器上迭代来使用全部的值:

>>> nested = [[1,2],[3,4],[5]]
>>> for num in flatten(nested):
    print num
    
1
2
3
4
5

 

 2.2 递归生成器

上面的例子中只能处理两层嵌套,若是不知道有多少层嵌套呢?咱们就要求助于递归了:

__metaclass__ = type
 
def flatten(nested):
    try:
        for sublist in nested:
            for element in sublist:
                yield element
    except TypeError:
        yield nested

当flatten被调用时,有两种可能性:基本状况和须要递归的状况,在特殊状况中,展开的是一个列表,程序必须遍历全部的字列表,并对他们调用flatten。而后用另外一个for循环来产生被展开的子列表中的全部元素。

>>> nested = [[1,2],[3,4],[5,[6,[7]]]]
>>> for num in flatten(nested):
    print num

1
2
3
4
5
[6, [7]]

(上面的结果跟书《python基础教程(第二版)》中例子的结果不同,我也搞不懂)

相关文章
相关标签/搜索