The difference between Python generator next method and send method

  python

Introduction to generator

In python, an object containing the yield keyword is a generator that is invoked every timenextThe method is executed untilyieldThe following statement, and then returnyieldThe execution results of the following code blocks. In fact, you can also call the send method
The following is an example for easy understanding.

Next method

def foo():
    bar_a = yield 1         # bar_a是语句块(yield 1)的返回值,默认为None
    bar_b = yield bar_a
    yield "最后一个值,再迭代就要报StopIteration了"

f = foo()                   # 创建生成器,此时没有执行foo()里的任何语句
print(next(f))              # 从foo()里进入,一直执行到(yield 1)处,此时变量bar_a还没有创建
print(next(f))              # 先将语句块(yield 1)的返回值赋值个bar_a,此时bar_a的值是None。
                            # 然后执行到语句块(yield bar_a),bar_b也还没有被创建
print(next(f)

Output:

>>>1
>>>None
>>>最后一个值,再迭代就要报StopIteration了

As can be seen,f = foo()When creating a generator, each time you execute toyieldWhen, will jump out and willyieldThe content following the keyword is returned to the caller. The next time another caller calls the generator again, it will first restore the generator’s last machine state and then execute the instruction encounter.yieldOr the element iteration is complete.
And we can see thatbar_aAndbar_bYes statementyield 1Andyield bar_aNote that:Is not the return value of the generator.
There is a place around here, we usebar_a = yield 1Do analysis:

  • 1 is the return value of the generator. Because the generator returnsyieldThe following code block
  • Bar_a is a statementyield 1Return value of, this is like we write

    a = print('my lover')
    Print('a's value is:', a)

    Output:

    >>>my lover
    The value of > > > a is: None

Send method

def foo():
    bar_a = yield 1
    bar_b = yield bar_a
    yield "最后一个值,再迭代就要报StopIteration了"

f = foo()
print(f.send(None))
print(f.send("my lover"))
print(next(f))

Output:

>>>1
>>>my lover
>>>最后一个值,再迭代就要报StopIteration了

Heref.send(None)Is the initialization generator, andnext(f)The effect is exactly the same. However, this is not recommended because it is not standard.
Note that the second line of output is the string mylove, not None. This is becausesendThe function has a parameter that overrides theyield 1The return value of the statement, bar_a, is now not None.

FAQ

The official website mentioned that when we create a generator, the first call can only be made withnext()Or ..send(None). Because there is no yield statement to receive other parameters passed in by send at this time.
I can’t understand this sentence. It seems that when it is passed into None, yield will receive it. If you understand, please give us some advice.
The original text and the portal are as follows:

Official website portal

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.

Google translation:
Resumes execution and “sends” the value to the generator function. The value parameter becomes the result of the current output expression. The send () method returns the next value generated by the generator, or StopIteration throws if the generator exits without generating another value. When send () calls the startup generator, it must call None as a parameter because there is no yield expression that can receive the value.


Update:
2018-11-24
Use for generatorssend(None)Method, the interpreter calls at the bottom__next__Method, that isnext()Method