Python迭代器(iterator)和生成器(generator)
一、迭代器(iterator)
在Python中,for循环可以用于Python中的任何类型,包括列表、元祖等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器
迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。任何这类的对象在Python中都可以用for循环或其他遍历工具迭代,迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开。
使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。
比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:
1for line in open("test.txt").readlines():
2 print line
这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。
利用file的迭代器,我们可以这样写:
1for line in open("test.txt"): #use file iterators
2 print line
这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。还有一个很明显的例子,xrange函数优于range函数就在于此:
1for i in range(1000): pass
2与
3for i in xrange(1000): pass
会导致生成一个 1000 个元素的 List,该函数在运行中占用的内存会随着参数的增大而增大,如果要控制内存占用,最好不要用 List来保存中间结果,而是通过 iterable 对象来迭代。每次迭代中返回下一个数值,内存空间占用很小。
二、生成器(Generators)
生成器函数在Python中与迭代器协议的概念联系在一起。简而言之,包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。函数也许会有个return语句,但它的作用是用来yield产生值的。
不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效
1>>> def g(n):
2... for i in range(n):
3... yield i **2
4...
5>>> for i in g(5):
6... print i,":",
7...
80 : 1 : 4 : 9 : 16 :
要了解他的运行原理,我们来用next方法看看:
1>>> t = g(5)
2>>> t.next()
3>>> t.next()
41
5>>> t.next()
64
7>>> t.next()
89
9>>> t.next()
1016
11>>> t.next()
12Traceback (most recent call last):
13 File "<stdin>", line 1, in <module>
14StopIteration
在运行完5次next之后,生成器抛出了一个StopIteration异常,迭代终止。再来看一个yield的例子,用生成器生成一个Fibonacci数列(斐波那契数列):
1def fab(max):
2 a,b = 0,1
3 while a < max:
4 yield a
5 a, b = b, a+b
6>>> for i in fab(20):
7... print i,",",
8...
90 , 1 , 1 , 2 , 3 , 5 , 8 , 13 ,
再来一个使用yield 生成器的示例:
1def read_file(fpath):
2 BLOCK_SIZE = 1024
3 with open(fpath, 'rb') as f:
4 while True:
5 block = f.read(BLOCK_SIZE)
6 if block:
7 yield block
8 else:
9 return
如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取 。
参考页面:
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/python-iterator-generator/5079.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.