Deep understanding of Python yield

https://blog.csdn.net/lftaoyuan/article/details/78915518

 

python2 and python3 are incompatible, the whole environment is python3.6

Simple yield instance

It used to be only a rough idea of ​​what yielddata can be used to return a value to a function, such as the following example:

def addlist(alist):
    for i in alist: yield i + 1
  • 1
  • 2
  • 3

Take alisteach item out and i + 1stuff it in. Then fetch each item by calling:

alist = [1, 2, 3, 4]
for x in addlist(alist): print(x)
  • 1
  • 2
  • 3

This is indeed yieldan example of an application, but after reading a lot of things and experiencing it repeatedly, I have a new understanding of yield, and this one is a masterpiece.

function containing yield

If you see that a function is included yield, it means that the function is already a function Generator, and its execution will be very different from other ordinary functions. For example the following simple function:

def h():
    print('study yield') yield 5 print('go on!') h()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

As you can see, h()after the call, the print statement is not executed! This is it yield. The specific content will become more and more clear later, including yieldthe working principle.

yield is an expression

Before python 2.5, it yieldwas a statement, and I didn't verify it, because it was no longer used, and now it yieldis an expression:

m = yield 5
  • 1

The return value of the expression (yield 5) will be assigned to m, so it m = 5 must be wrong.

So how to get the return value of (yield 5)? need to be used send(msg).

How yield works

yieldThe working principle of the disclosure needs to be matched with the function next(). The above h()is not executed after being called because it has yieldan expression that next()can resume Generatorexecution until the next one yield.

def h():
    print('study yield') yield 5 print('go on!') c = h() d1 = next(c) # study yield d2 = next(c) """ study yield go on! Traceback (most recent call last): File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module> d2 = next(c) StopIteration """
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

next()After being called, it h()starts executing until it encountersyield 5

So the output is:study yield

When we call it again next(), execution continues until the next one is found yield. Since there is no later yield, an exception will be thrown:

study yield
go on!
Traceback (most recent call last):
  File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module> d2 = next(c) StopIteration
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

send(msg) 与 next()

Now that we know next()how to make the included yieldfunction execute, let's look at another very important function send(msg).

In fact next(), send()it is similar to the effect in a certain sense

the difference

send()yieldvalue that can be passed

next()Only pass None.

So the next() effect  send(None)is the same.

def s():
    print('study yield') m = yield 5 print(m) d = yield 16 print('go on!') c = s() s_d = next(c) # 相当于send(None) c.send('Fighting!') # (yield 5)表达式被赋予了'Fighting!'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

The output is:

study yield
Fighting!
  • 1
  • 2

Note When the generator is just started (the first call), please use the next()statement or send(None), you cannot directly send a non-None value, otherwise it will be reported TypeError, because there is no yieldstatement to receive this value.

The return value of send(msg) and next()

send(msg) The return value of and  next() is special and is the parameter of the next yieldexpression (yield 5, then return 5).

Here, in the first example, through for i in alist traversal  Generator, it is actually called every time next(), and next()the return value each time is yieldthe parameter:

def s():
    print('study yield') m = yield 5 print(m) d = yield 16 print('go on!') c = s() s_d1 = next(c) # 相当于send(None) s_d2 = c.send('Fighting!') # (yield 5)表达式被赋予了'Fighting!' print('My Birth Day:', s_d1, '.', s_d2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Output result:

study yield
Fighting!
My Birth Day: 5 . 16
  • 1
  • 2
  • 3

Interrupt Generator

In the above example, when there is no executable program, one will be thrown StopIteration. During the development process, interrupting the Generator is a very flexible technique

throw

Terminate the Generator by throwing a GeneratorExit exception.

close

The function of close is the same as that of throw. Looking at its source code, you can find that it is the same as raise.

def throw(self, type, value=None, traceback=None):
    '''Used to raise an exception inside the generator.''' # 用于在生成器中抛出一个异常。 pass def close(self): '''Raises new GeneratorExit exception inside the generator to terminate the iteration.''' # 在生成器中生成新的GeneratorExit异常来终止迭代。 pass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

In fact, the last interrupt generator can be ignored. In the development process, it is inevitable to use these, but Python3 has done a good job internally, and it is generally not necessary to do this manually.

demo ruins

https://github.com/seeways/PythonDemo/blob/master/static/yield_demo.py

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325053377&siteId=291194637