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 yield
data 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 alist
each item out and i + 1
stuff 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 yield
an 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 yield
the working principle.
yield is an expression
Before python 2.5, it yield
was a statement, and I didn't verify it, because it was no longer used, and now it yield
is 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
yield
The 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 yield
an expression that next()
can resume Generator
execution 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 yield
function 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()
yield
value 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 yield
statement 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 yield
expression (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 yield
the 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