[size=x-large][b]Python中的生成器[/b][/size]
[size=medium][b]1. 什么是生成器:[/b][/size]
在《Python核心编程》中有个定义:
[quote="《Python核心编程》"]挂起返回出中间值并多次继续的协同程序被称为生产器,那就是Python的生成器真正做的事情[/quote]
那么什么是协同程序呢?
[quote="《Python核心编程》"]协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始[/quote]
首先可以理解为:
[list]
[*]生成器是函数
[*]生成器可以在执行过程中返回中间值,并继续执行。
[/list]
[size=medium][b]2. python中的生成器[/b][/size]
在python中生成器就是一个带yield的函数,yield能返回一个值给调用者,并暂停运行,当生成器的next()方法被调用的时候,它会继续从离开的地方继续
[size=medium][b]3. 示例[/b][/size]
>>> f = fab(5)
>>> f.next()
>>> 1
>>> f.next()
>>> 1
>>> f.next()
>>> 2
>>> f.next()
>>> 3
>>> f.next()
>>> 5
>>> f = fab(5)
>>> for i in f:
.... print i
1
1
2
3
5
[size=medium][b]4.运用场景[/b][/size]
乍一看,生成器和迭代器差不多,功能也很相似,那么什么情况下用生成器呢。
一个明显的运用场景是要处理[color=blue]一个大的数据集[/color]的时候,比如一个10G的文件,
如果用迭代的话,会产生很大的内存占用,如果用生成器的话就不会有这个问题
[quote]列表解析式:
[expr for iter_var in iterable if cond_expr][/quote]
[quote]生成器表达式:
(expr for iter_var in iterable if cond_expr)[/quote]
比如一个10G的文件test_large
迭代式:
在运行过程中用pmap查看其内存占用
total 294096K
这个结果是我在运行中查看的,只运行了10s左右
生成器:
在运行过程中用pmap查看其内存占用
total 32024K
这个内存占用量直到运行结束都是这么多
[quote]这仅仅是因为一个语言这样的特征不意味着你需要用它。如果在你程序里没有明显适合的话,那就别增加多余的复杂性!当你遇到合适的情况时,你便会知道什么时候生成器正是要使用的东西。[/quote]
[size=medium][b]5. 在tornado中的运用[/b][/size]
这个并没有详细的研究,只是遇到的时候使用,在tornado中主要是在异步机制中会用到yield。
内部机制如何没有仔细研究,这应该是生成器运动的一个场景,[color=blue]需要长时间执行的程序[/color]
[b][size=medium]6. 总结[/size][/b]
[list]
[*]大数据集使用生成器
[*]需要长时间运行的操作,防止阻塞,不过需要借助其它的机制转换成异步操作,如celery
[/list]
[size=medium][b]1. 什么是生成器:[/b][/size]
在《Python核心编程》中有个定义:
[quote="《Python核心编程》"]挂起返回出中间值并多次继续的协同程序被称为生产器,那就是Python的生成器真正做的事情[/quote]
那么什么是协同程序呢?
[quote="《Python核心编程》"]协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始[/quote]
首先可以理解为:
[list]
[*]生成器是函数
[*]生成器可以在执行过程中返回中间值,并继续执行。
[/list]
[size=medium][b]2. python中的生成器[/b][/size]
在python中生成器就是一个带yield的函数,yield能返回一个值给调用者,并暂停运行,当生成器的next()方法被调用的时候,它会继续从离开的地方继续
[size=medium][b]3. 示例[/b][/size]
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
>>> f = fab(5)
>>> f.next()
>>> 1
>>> f.next()
>>> 1
>>> f.next()
>>> 2
>>> f.next()
>>> 3
>>> f.next()
>>> 5
>>> f = fab(5)
>>> for i in f:
.... print i
1
1
2
3
5
[size=medium][b]4.运用场景[/b][/size]
乍一看,生成器和迭代器差不多,功能也很相似,那么什么情况下用生成器呢。
一个明显的运用场景是要处理[color=blue]一个大的数据集[/color]的时候,比如一个10G的文件,
如果用迭代的话,会产生很大的内存占用,如果用生成器的话就不会有这个问题
[quote]列表解析式:
[expr for iter_var in iterable if cond_expr][/quote]
[quote]生成器表达式:
(expr for iter_var in iterable if cond_expr)[/quote]
比如一个10G的文件test_large
迭代式:
In [29]: f = open('test_large')
In [35]: sum([len(word) for line in f for word in line.split()])
在运行过程中用pmap查看其内存占用
total 294096K
这个结果是我在运行中查看的,只运行了10s左右
生成器:
In [32]: f.seek(0)
In [33]: sum(len(word) for line in f for word in line.split())
在运行过程中用pmap查看其内存占用
total 32024K
这个内存占用量直到运行结束都是这么多
[quote]这仅仅是因为一个语言这样的特征不意味着你需要用它。如果在你程序里没有明显适合的话,那就别增加多余的复杂性!当你遇到合适的情况时,你便会知道什么时候生成器正是要使用的东西。[/quote]
[size=medium][b]5. 在tornado中的运用[/b][/size]
这个并没有详细的研究,只是遇到的时候使用,在tornado中主要是在异步机制中会用到yield。
@tornado.gen.coroutine
def get(self):
res = yield self.db.welecome.find_one()
res = res['message']
self.render('index.html', message="hello world", tick=res)
内部机制如何没有仔细研究,这应该是生成器运动的一个场景,[color=blue]需要长时间执行的程序[/color]
[b][size=medium]6. 总结[/size][/b]
[list]
[*]大数据集使用生成器
[*]需要长时间运行的操作,防止阻塞,不过需要借助其它的机制转换成异步操作,如celery
[/list]