Generator Functions

If we replace the code at the end of the frange() function as shown in the following code snippet, we will turn the function into a generator. Generators do not have return statements; instead, they have yield statements. If a generator runs out of values, that is, if control reaches the end of the function, instead of returning, Python automatically raises a Stoplteration exception:

# Build and return a list # Return each value on demand result = [] while start < (stop - (inc / 2.0)):

while start < (stop - (inc / 2.0)): yield start result.append(start) start += inc start += inc return result

Now, if we call frange(5), we will get back a generator object, not a list. We can force the generator to give us a list by doing this: list(frange(5)). But a more common use of generators is in loops:

This will output "0.01.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0" whichever version we use. But for long lists the generator version will be much more efficient, because rather than creating the whole list in memory like the list version, it creates only one item at a time.

The yield statement behaves like a return statement, but for one crucial difference: After yield has returned a value, when the generator is next called it will continue from the statement following the yield with all its previous state intact. So the first time the frange() generator is called, assuming, say frange(5), it returns 0.0; the second time it returns 1.0, and so on. After returning 9.0 the while expression evaluates to False and the function terminates.

★Mutable parameters in Python are similar to Pascal's var parameters and to C++'s non-const references.

Because the function is a generator (and this is the case purely because we have used yield), when it finishes it does not return a value, but instead raises a StopIteration exception. In the context of a for loop, the for gracefully handles this particular exception, taking it not as an error, but as an indication that the iteration has completed, so the for loop ends and the flow of control moves to the for loop's else suite, or to the statement following the for loop's suite, if there is no else. Similarly, if we coerce a generator into a list, the list constructor will automatically handle the StopIteration exception.

A generator is an object that has a next() function, so we can explore the behavior of our frange() generator interactively if we wish:

>>> list(frange(1, 3, 0.75)) [1, 1.75, 2.5]

>>> gen = frange(1, 3, 0.75) >>> gen.next() 1

Traceback (most recent call last): File <pyshell#126>, line 1, in -toplevel-gen.next() StopIteration

We generated the whole three-item list using list(), and then we used the generator returned by frange() to produce each successive value in the same way that a for loop does.

Was this article helpful?

0 0
Tuberminator

Tuberminator

The main focus of this report is to show how to get involved in video marketing on the run, how to rank quickly on YouTube and Google using FREE semi-automatic tools and services. QUICKLY AND FREE. I will show methods and techniques I use to rank my videos, as well as free resources and tools to make video clips, to get backlinks and free traffic.

Get My Free Ebook


Post a comment