标签:python generator functions yield
本篇笔记记录自己对Python的generator functions和yield表达式的理解。
1. Generator Functions
Python支持的generator functions语法允许我们定义一个行为与iterator类似的函数,它可以被用在需要循环调用的场合。与普通函数相比,generator functions只是在函数定义中多了1个yield表达式,除此之外,没有其它特别之处。>>> s = sum(xrange(1000000)) >>> p = product(xrange(1000000))再对比另一种实现方式:
>>> nums = list(xrange(1000000)) >>> s = sum(nums) >>> p = product(nums)
很显然,第1种方式调用sum和product时会分别生成1次元素为integer的大集合,而第2种方式只会生成1次并存放在内存供后续使用中。在我们的假设场景下,第2种方式会更节省时间(典型的空间换时间)。不过,如果机器内存受限以至于无法hold住大集合,则只能采用第1种实现方式(时间换空间的折衷方式),即使其性能有损耗。
除支持generator functions外,python还支持generator expressions语法。关于generator的详细说明,强烈建议精读PYTHON - GENERATOR FUNCTIONS AND EXPRESSIONS这篇文章 。
2. yield表达式
从官网文档可知,yield表达式只能用于generator function的定义体中,也即,只要某函数定义中出现了yield表达式,该函数就成了generator函数,而不再是个普通函数。
我们可以从"yield"的字面含义来理解yield表达式的行为:程序运行至该表达式时,会暂时"放弃"继续向下执行的权利,程序控制权会返回给其调用者且由yield表达式"产生"的值也会返回给caller,此外,函数执行yield表达式后挂起时的context(包括那个时刻函数的local scope和local variables等信息)会被保存下来以便后续恢复执行现场(与CPU处理中断信号的过程非常类似)。
当然,仅从字面意思推断yield表达式行为的思路并不严谨,这样解释只是为了辅助理解。下面是PYTHON -
GENERATOR FUNCTIONS AND EXPRESSIONS一文中出现的关于generator functions和yield表达式行为的更严谨解释:
Normal functions return a value and then exit. But generator functions automatically suspend and resume their execution. Because of that, they are often a useful alternative to both computing an entire series
of values up front and manually saving and restoring state in classes. Because the state that generator functions retain when they are suspended includes their local scope, their local variables retain information and make it available when the functions are
resumed.
The primary difference between generator and normal functions is that a generator yields a value, rather than returns a value. The yield suspends the function and sends a value back to the caller while retains
enough state to enable the function immediately after the last yield run. This allows the generator function to produce a series of values over time rather than computing them all at once and sending them back in a list.
>>> def create_counter(n): print('create_counter()') while True: yield n print('increment n') n += 1 >>> c = create_counter(2) >>> c <generator object create_counter at 0x03004B48> >>> next(c) create_counter() 2 >>> next(c) increment n 3 >>> next(c) increment n 4 >>>上面的代码用def定义了名为create_counter的generator function来实现计数器功能。
真正理解了上面代码的输出后,相信我们也会真正理解yield表达式和generator function的语法行为。
此外,Improve Your Python: ‘yield‘ and Generators Explained这篇文章最后部分对generator和yield表达式做了非常精炼且准确的总结,摘录如下:
1) generators are used to generate a series of values
2) yield is like the return of generator functions
3) The only other thing yield does is save the "state" of a generator function
4) A generator is just a special type of iterator
5) Like iterators, we can get the next value from a generator using next()
6) for gets values by calling next() implicitly
相信有了本篇笔记前面的介绍,这几点很容易理解。
#!/bin/env python def fib(threshold): a, b = 0, 1 while a < threshold: yield a a, b = b, a + b def main(): for n in fib(100): print n if '__main__' == __name__: main()
【参考资料】
1.
Python Docs: Yield expressions
2.
PYTHON - GENERATOR FUNCTIONS AND EXPRESSIONS
3.
Improve Your Python: ‘yield‘ and Generators Explained
4. Python PEP 255 -- Simple Generators
5. Python PEP 342 -- Coroutines via Enhanced Generators
========================= EOF =============================
【Python笔记】如何理解python中的generator functions和yield表达式
标签:python generator functions yield
原文地址:http://blog.csdn.net/slvher/article/details/41207109