参考自:http://www.cnblogs.com/huxi/category/251137.html
迭代器
迭代器是访问集合内元素的一种方式,他不能倒退只能一直迭代下去。可以写到for循环in后面的对象都是可迭代的,比如list,dict,字符串等。
迭代器的一个优点就是它不要求你事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如很大的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)。
迭代器提供了一个统一的访问集合的接口。只要是实现了__iter__()方法的对象,就可以使用迭代器进行访问。
iter获取迭代对象,next()方法访问下一个元素,访问越界会有stopIteration。
python中的 for循环会自动调用iter()获得迭代器,next()下一个元素,自动检测StopIteration。
自己实现一个迭代器,如上所述,只需要在类的__iter__方法中返回一个对象,这个对象拥有一个next()方法,这个方法能在恰当的时候抛出StopIteration异常即可。但是需要自己实现迭代器的时候不多,即使需要,使用生成器会更轻松。
上图 圆括号为生成器表达式,返回迭代器,方括号为列表解析,他们俩很相似,一般都说列表解析,但是在生成的数据很大或明确要列表的时候,用生成器表达式更佳。
列表解析(生成器表达式)是很pythonic的一种写法。
列表解析可以替代绝大多数需要用到map和filter的场合,可能正因为此,著名的静态检查工具pylint将map和filter的使用列为了警告。
生成器
生成器是迭代器,同时也并不仅仅是迭代器,不过迭代器之外的用途实在是不多,所以可以说:生成器提供了非常方便的自定义迭代器的途径。
生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。另外,对于生成器的特殊语法支持使得编写一个生成器比自定义一个常规的迭代器要简单不少,所以生成器也是最常用到的特性之一。
#Fibonacci
def fib_opt(n):
a,b,i=0,1,0
while i<n:
a,b=b,a+b
i+=1
else:
return b
print [fib_opt(i) for i in range(100)] 在算100的时候,前面99个还是要重新计算。重复计算了很多次。
包含yield语句的函数会被编译成生成器。生成器是惰性求值的。
当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。不像一般的函数会返回生成值后退出,生成器函数在返回生成值后会自动挂起并暂停他们的执行和状态变量将被保存,这些信息在函数恢复时将再度有效。
def fib_iter():
a, b = 0, 1
while True:
yield b
a, b = b, a + b
迭代中每次都会返回迭代值,但是下次调用的时候,他继续之前的计算而不是重新计算。
import time start = time.clock()
opt_result = [fib_opt(i) for i in range(10000)]
end = time.clock()
print end - start print "------------------------------"
A = fib_iter()
start = time.clock()
iter_result = [A.next() for i in xrange(10000)]
end = time.clock()
print end - start
差了3000倍
yield除了next还有send方法。yield可以使用send方法向函数传递参数。
Itertools
import itertools horses=[1,2,3,4]
races = itertools.permutations(horses) a=itertools.product([1,2],[3,4])
b=itertools.repeat([1,2],4) c=itertools.chain(races, a, b) print [i for i in c]
这个工具 返回的 races,a,b都是迭代器,permutation为所有的两两组合。product为第一个列表和第二个列表中各取一个组合,repeat上面为[1,2]重复四次,chain为连起来。
更多的内容可以去查阅官方文档。