2013年5月17日 星期五

Python的yield

先從Python Official Documentation看起對於yield的解釋

Python 2.7.5 version definition (python2.7.5好像還是視yield為statement?????)

6.8. The yield statement

yield_stmt ::=  yield_expression
The yield statement is only used when defining a generator function, and is only used in the body of the generator function. Using a yieldstatement in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.
When a generator function is called, it returns an iterator known as a generator iterator, or more commonly, a generator. The body of the generator function is executed by calling the generator’s next() method repeatedly until it raises an exception.
When a yield statement is executed, the state of the generator is frozen and the value of expression_list is returned to next()‘s caller. By “frozen” we mean that all local state is retained, including the current bindings of local variables, the instruction pointer, and the internal evaluation stack: enough information is saved so that the next time next() is invoked, the function can proceed exactly as if the yield statement were just another external call.
As of Python version 2.5, the yield statement is now allowed in the try clause of a try ... finally construct. If the generator is not resumed before it is finalized (by reaching a zero reference count or by being garbage collected), the generator-iterator’s close() method will be called, allowing any pending finally clauses to execute.
For full details of yield semantics, refer to the Yield expressions section.
Note

In Python 2.2, the yield statement was only allowed when the generators feature has been enabled. This __future__ import statement was used to enable the feature:
from __future__ import generators



Generators和yield之間的關係:

'yield'從python2.5開始,由statement轉成expression。而'yield'就像function的return value一樣,能回傳值出來,但本身又不會結束函式的執行(除非已執行到函式結束為止,才會丟exception)。因為yield只是暫時轉換執行的控制權,並回傳值給原本呼叫它的程式(caller),所以才可以利用yield來產生一系列的值,而擁有'yield'的函式 (function)我們稱之為"generator function(生成器函式)",而yield本身就像是generator function的return一樣。

"Yield," however, implies that the transfer of control is temporary and voluntary, and our function expects to regain it in the future.
In Python, "functions" with these capabilities are called generators, and they're incredibly useful.generators (and the yield statement) were initially introduced to give programmers a more straightforward way to write code responsible for producing a series of values. 

  • generators are used to generate a series of values
  • yield is like the return of generator functions
  • The only other thing yield does is save the "state" of a generator function
  • generator is just a special type of iterator
  • Like iterators, we can get the next value from a generator using next()
    • for gets values by calling next() implicitly


yield (生成器)好似是個比較難理解的概念.
當這個生成器被執行時.將會回傳一個 itertor.
之後便可以通過 next() 或者是 send(something) 來呼叫
而他執行後會記住上一次的執行結果..之後再繼續執行 




再從良葛格筆記看'yield'的解釋:




從Python 2.5開始,yield從陳述句(statement)改為運算式(expression),也就是yield除了「產生」指定的值之外,會有一個運算結果,yield運算結果預設是None,你可以透過產生器的send()方法傳入一個值,這個值就成為yield的運算結果。這給了你一個與產生器溝通的機會。例如:

>>> def myrange(n):
...     x = 0
...     while True:
...         val = (yield x)
...         if val is not None:
...             x = val
...         else:
...             x += 1
...         if x >= n:
...             break
...
>>> g = myrange(10)
>>> next(g)
0
>>> next(g)
1
>>> next(g)
2
>>> g.send(0)
0
>>> next(g)
1
>>> next(g)
2
>>> g.send(5)
5
>>> next(g)
6
>>> next(g)
7
>>>





Reference:

1. http://openhome.cc/Gossip/Python/YieldGenerator.html
2. Improve your Python: 'yield' and 'generator' explained, http://www.jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/

沒有留言:

張貼留言