一. 迭代器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基础教程(第二版)》中例子的结果不同,我也搞不懂)