Python "exit" behavior

I am reading about the yield keyword in python and trying to figure out the launch of this example:

 def countfrom(n): while True: print "before yield" yield n n += 1 print "after yield" for i in countfrom(10): print "enter for loop" if i <= 20: print i else: break 

Output:

 before yield enter for loop 10 after yield before yield enter for loop 11 after yield before yield enter for loop 12 after yield before yield enter for loop 13 after yield before yield enter for loop 14 after yield before yield enter for loop 15 after yield before yield enter for loop 16 after yield before yield enter for loop 17 after yield before yield enter for loop 18 after yield before yield enter for loop 19 after yield before yield enter for loop 20 after yield before yield enter for loop 

It seems that the income will return the specified value and continue to execute the function until the end (possibly in a parallel thread). I understand correctly?

If you could answer this question without mentioning the “generators”, I would be grateful because I am trying to understand it at a time.

+8
python yield
source share
6 answers

You can think of it as if the function that yield simply “pauses” when it meets yield . The next time you call it, it will return after yield , preserving the state it was in when it left.

+20
source share

No, there is only one thread.

Each iteration of the for loop executes your countFrom function until it gives something or returns. After the exit, the body of the for loop starts again, and then, when a new iteration begins, the countFrom function selects exactly where it was stopped, and starts again until it gives (or returns).

This modified version of your example will help make it clearer what the path is.

 def countfrom(n): while n <= 12: print "before yield, n = ", n yield n n += 1 print "after yield, n = ", n for i in countfrom(10): print "enter for loop, i = ", i print i print "end of for loop iteration, i = ", i 

Exit

 before yield, n = 10 enter for loop, i = 10 10 end of for loop iteration, i = 10 after yield, n = 11 before yield, n = 11 enter for loop, i = 11 11 end of for loop iteration, i = 11 after yield, n = 12 before yield, n = 12 enter for loop, i = 12 12 end of for loop iteration, i = 12 after yield, n = 13 
+6
source share

.. you cannot explain the meaning of the yield without mentioning generators; it would be like trying to explain what a stone is without mentioning the rock. That is: the yield statement is responsible for converting a normal function to a generator.

So far, you find this well documented here: http://docs.python.org/reference/simple_stmts.html#the-yield-statement

.. a brief explanation of this:

  • When a function that uses the yield statement is called, it returns a “generator iterator” that has a .next() method (standard for iterables)
  • Each time the generator .next() method is .next() for example, by iterating an object with a for loop), the function is called until the first output is encountered. Then the execution of the function is suspended and the value is passed as the return value of the .next() method.
  • The next time .next() is called, the function resumes until the next yield , etc., until the function returns anything.

Some of the benefits are:

  • less memory use, because memory is allocated only for the current value, and not for the entire list of returned values ​​(since this would be by returning a list of values)
  • "real-time return" returns the result, as they are created, can be passed to the caller without waiting for the generation to finish (I used this to return the output from the running process).
+4
source share

The countfrom function countfrom not execute in a parallel thread. What happens here is that whenever for -construct asks for the next value, the function will execute until it hits the yield . When the next value after that is required, the function resumes execution from where it was stopped.

And although you asked not to mention “generators”, they are so closely related to yield that in fact it makes no sense to talk about separateness. What your countfrom function actually returns is a "generator object." It returns this object immediately after its call, so the function body is not executed at all until something (for example, a for -loop) requests a value from the generator using its .next() method.

+1
source share

The yield statement stores the value you give until this function is called again. therefore, if you call this function (with an iterator), it will run the function at another time and give you a value. the bottom line is that he knows where he stayed last time

0
source share

Python runs until it reaches the yield value, and then stops and freezes the execution. This does not go on. He presses the “after” next call to countfrom

It is easy to say that without reference to the generators, but the fact is the way out, and the generator is inextricably linked. To truly understand this, you must consider them as one and the same topic.

It is easy to show that what I (and others) said is true, working with the generator from your example more manually.

A function that yield instead of return ing does return a generator. Then you can use this generator by calling next . You are baffled because your loop takes care of everything you like.

Here with open insides:

 def countfrom(n): while n <= 12: print "before yield, n = ", n yield n n += 1 print "after yield, n = ", n your_generator = countfrom(10) next(your_generator) print "see the after yield hasn't shown up yet, it stopped at the first yield" next(your_generator) print "now it woke back up and printed the after... and continued through the loop until it got to back to yield" next(your_generator) print "rinse and repeate" 
0
source share

All Articles