SoFunction
Updated on 2024-11-17

Python Deeper Understanding of Yield

It's only roughly known that yield can be used to stuff data for a function return value, as in the following example:
def addlist(alist):
    
for i in alist:
        
yield i + 1
Take out each item of alist and stuff i + 1 into it. Then take out each item by calling:
alist = [1234]
for x in addlist(alist):
    
print x,
This is indeed an example of a yield application, but having read limodou's article "TheLearning experience of version 2.5 of yield", and after experiencing it over and over again on my own, I have a whole new understanding of yield.

1. Functions containing yield

If you see that a function contains a yield, it means that the function is already a Generator and its execution will be a lot different from other normal functions. For example, the following simple function:
def h():
    
print 'To be brave'
    
yield 5

h()
As you can see, the print statement does not execute after calling h()! That's yield, so how do you get the print statement to execute? This is the question to be discussed later, through the discussion and learning later, you will understand the workings of yield.

2. yield is an expression

Before Python 2.5, a yield was a statement, but now in 2.5, a yield is an Expression, for example:
= yield 5
The return value of the expression (yield 5) will be assigned to m, so it is wrong to assume that m = 5. So how do you get the return value of (yield 5)? You need to use the send(msg) method, which will be introduced later.

3. Through the next () statement to see the principle of

Now, let's reveal how yield works. We know that our h() above is not executed when it is called because it has a yield expression, so we make it execute by next() statement. next() statement will resume the Generator execution and go till the next field expression. For example:
def h():
    
print 'Wen Chuan'
    
yield 5
    
print 'Fighting!'

= h()
()
() call, h() starts executing until it encounters yield 5 and therefore outputs the result:
Wen Chuan
When we call () again, execution will continue until the next yield expression is found. Since there are no more yields, an exception is thrown:
Wen Chuan
Fighting!
Traceback (most recent call last):
  File 
"/home/evergreen/Codes/", line 11in <module>
    ()
StopIteration

4. send(msg) vs. next()

Understand how next () contains a function of the execution of the field, we look at another very important function send (msg). In fact, next () and send () in a sense that the role is similar, the difference is that send () can be passed into the value of the field expression, and next () can not pass a specific value, can only pass None into. Therefore, we can look at it as
() and (None) work the same way.
Take a look at this example:
def h():
    
print 'Wen Chuan',
    m 
= yield 5  # Fighting!
    print m
    d 
= yield 12
    
print 'We are together!'

= h()
()  
#equal
('Fighting!')  #(yield 5) expression is given 'Fighting!'
The output is:
Wen Chuan Fighting!
Please note that the first time you call it, please use the next() statement or send(None), you can't use send to send a value that is not None, or you will get an error, because there is no yield statement to receive the value.

5. return values of send(msg) and next()

send(msg) and next() do have return values, and their return values are special in that they return the arguments to the next yield expression. For example, if field 5 is returned, then 5 is returned. Here, is not to understand something something? In this paper, the first example, by for i in alist traversing the Generator, in fact, each time the call (), and each time the return value of () is the parameters of the yield, that is, we began to think that was pressed into the east. Let's continue the above example:
def h():
    
print 'Wen Chuan',
    m 
= yield 5  # Fighting!
    print m
    d 
= yield 12
    
print 'We are together!'

= h()
= ()  #m gets the value of field 5's argument 5
= ('Fighting!')  #d The value of the field 12 parameter 12 is obtained.
print 'We will never forget the date', m, '.', d
Output results:
Wen Chuan Fighting!
We will never forget the date 5 . 12

6. throw() together with close()disruptions Generator

Interrupting the Generator is a very flexible technique to terminate the Generator by throwing a GeneratorExit exception. the Close() method does the same thing, in fact internally it calls throw(GeneratorExit). Let's see:
def close(self):
    
try:
        (GeneratorExit)
    
except (GeneratorExit, StopIteration):
        
pass
    
else:
        
raise RuntimeError("generator ignored GeneratorExit")
# Other exceptions are not caught
Therefore, if we call next() or send(msg) after calling the close() method, an exception will be thrown:
Traceback (most recent call last):
  File 
"/home/evergreen/Codes/", line 14in <module>
    d 
= ('Fighting!')  #d The value of the field 12 parameter 12 is obtained.
StopIteration

Note: The above views belong to my personal understanding, if there is any deviation, please criticize and correct. Thank you!