78915518
Python2 and Python3 are incompatible, and the entire environment is python3.6
A simple yield instance
Previously it was only sketchy to know what yield
can be used to return value plug data for a function, such as the following example:
def addlist(alist): for i in alist: yield i + 1
alist
take out each item and then i + 1
tuck it in. Each entry is then fetched by calling:
alist = [1, 2, 3, 4]for x in addlist(alist): print(x)
This is indeed yield
an example of application, but after seeing a lot of things and experiencing it over and over again, there is a whole new understanding of yield, which is a fine piece.
Functions that contain yield
If you see that a function yield
is contained, which means that the function is already one Generator
, its execution will be different from other normal functions. For example, the following simple function:
def h(): print(‘study yield‘) yield 5 print(‘go on!‘)h()
As you can see, h()
after the call, the print statement is not executed! This is yield
. The specific content will be more and more clear later, including yield
how it works.
Yield is an expression
Python 2.5 ago, yield
is a statement, I did not research, because it was not used, now yield
is an expression:
m = yield 5
The return value of the expression (yield 5) will be assigned to M, so it m = 5
must be wrong.
So how do you get the return value (yield 5)? Need to use send(msg)
.
How yield works
yield
The working principle of the announcement requires a matching next()
function. The above h()
is called after it is not executed, because it has an yield
expression that next()
can be resumed by Generator
execution until the next yield
.
def h(): print(‘study yield‘) yield 5 print(‘go on!‘)c = h()d1 = next(c) # study yieldd2 = next(c)"""study yieldgo on!Traceback (most recent call last): File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module> d2 = next(c)StopIteration"""
next()
After being called, h()
execution begins until it encountersyield 5
So the output is:study yield
When we call again next()
, we continue to execute until we find the yield
next. Because there is no later yield
, the exception is thrown out:
yieldgo on!Traceback (most recent call last): File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module> d2 = next(c)StopIteration
Send (MSG) with Next ()
next()
once we know how to make yield
the included function execute, let's look at another very important function send(msg)
.
next()
in fact, send()
it's similar in some sense.
Difference
send()
Values that can be passed yield
next()
Can only be passed None
.
So next()
send(None)
The function 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!‘
The result of the output is:
yieldFighting!
Note When the generator is started (first call), use the next()
statement or send(None)
not to send a value that is not none directly, 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)
and next()
The return value is special, is yield
the argument of the next expression (yield 5, returns 5).
Here, the first example, through for i in alist
traversal Generator
, is actually called every time next()
, and each time next()
the return value is exactly 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)
Output Result:
yieldFighting!My Birth Day: 5 . 16
Interrupt Generator
In the above example, when there is no executable program, it throws one StopIteration
, during the development process, interrupt generator is a very flexible technique
Throw
Terminates generator by throwing a generatorexit exception.
Close
The role of close and throw is the same, look at its source code, it can be found that it and raise a ball like
def throw(self, type, value=None, traceback=None): ‘‘‘Used to raise an exception inside the generator.‘‘‘ # 用于在生成器中抛出一个异常。 passdef close(self): ‘‘‘Raises new GeneratorExit exception inside the generator to terminate the iteration.‘‘‘ # 在生成器中生成新的GeneratorExit异常来终止迭代。 pass
In fact, the last interrupt generator can be ignored, in the development process, it is unavoidable to use these, but Python3 internal has done very well, and generally do not need to do this thing manually.
Demo Address
https://github.com/seeways/PythonDemo/blob/master/static/yield_demo.py
Deep understanding of Python yield