1. 程式人生 > >筆記-pytho-語法-yield

筆記-pytho-語法-yield

筆記-python-語法-yield

 

1.      yield

1.1.    yield基本使用

def fab(max):

    n,a,b = 0, 0, 1

    while n < max:

        yield b

        a, b = b, a+b

        n = n + 1

 

f = fab(7)

print(f)

for i in f:

print(i)

 

1.2.    解釋

在python 語法參考6.2.9中是這樣描述的:

The yield expression is used when defining a generator function or an asynchronous generator function and thus can only be used in the body of a function definition. Using a yield expression in a function’s body causes that function to be a generator, and using it in an async def function’s body causes that coroutine function to be an asynchronous generator. 

 

當一個生成器函式被呼叫時,它返回一個生成器(迭代器);

當它暫停時,會儲存

all local state, including the current bindings of local variables, the instruction pointer, the internal evaluation stack, and the state of any exception handling. 

 

1.3.    Generator-iterator methods

下面的章節描述了生成迭代器的方法,使用它們可以控制生成器函式的行為。

Note that calling any of the generator methods below when the generator is already executing raises a ValueErrorexception.

 

generator.__next__()

Starts the execution of a generator function or resumes it at the last executed yield expression. When a generator function is resumed with a __next__() method, the current yield expression always evaluates to None. The execution then continues to the next yield expression, where the generator is suspended again, and the value of the expression_list is returned to __next__()’s caller. If the generator exits without yielding another value, a StopIteration exception is raised.

This method is normally called implicitly, e.g. by a for loop, or by the built-in next() function.

 

generator.send(value)

Resumes the execution and “sends” a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is no yield expression that could receive the value.

 

generator.throw(type[, value[, traceback]])

Raises an exception of type type at the point where the generator was paused, and returns the next value yielded by the generator function. If the generator exits without yielding another value, a StopIteration exception is raised. If the generator function does not catch the passed-in exception, or raises a different exception, then that exception propagates to the caller.

 

generator.close()

Raises a GeneratorExit at the point where the generator function was paused. If the generator function then exits gracefully, is already closed, or raises GeneratorExit (by not catching the exception), close returns to its caller. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller. close() does nothing if the generator has already exited due to an exception or normal exit.

 

1.4.  Examples

Here is a simple example that demonstrates the behavior of generators and generator functions:

>>> def echo(value=None):
...     print("Execution starts when 'next()' is called for the first time.")
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception as e:
...                 value = e
...     finally:
...         print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.

 

1.5.    更多的案例

1.5.1.   example:1

def node._get_child_candidates(self, distance, min_dist, max_dist):

    if self._leftchild and distance - max_dist < self._median:

        yield self._leftchild

    if self._rightchild and distance + max_dist >= self._median:

        yield self._rightchild

 

1.5.2.   send案例

send有點不同

 

def func_yield():

    x = yield 8

    print(x)

    x = yield x+6

    print(x)

    x = yield 23

print(x)

return 14

   

a = func_yield()

 

print('step 1:')

print(a.send(None))

print('step 2:')

print(a.send(11))

print('step 3:')

print(a.send(12))

print(a.send(13))

輸出:

step 1:

8

step 2:

11

17

step 3:

12

23

13

Traceback (most recent call last):

  File "E:\python\person_code\python_foundation\python_other.py", line 403, in <module>

    print(a.send(13))

StopIteration: 14

 

send是先執行賦值後執行yield,

或者說x=yield 7等於

yield 7

x = val

最後一定是丟擲一個異常來結束。