Course 2.2Lesson 4 of 5
A generator is a function with yield in it. Calling it does not run the body but gives a generator object, an iterator. Each next runs the body until the next yield, gives that value, and pauses with all its variables kept, then continues from there when asked again. When the body ends, StopIteration is raised. A generator is a short way to write an iterator, and it can be endless, because values are made only when asked. itertools.islice takes the first few values of an endless generator. A generator expression is a comprehension in round brackets that does not build a list, so sum of a generator uses little memory, and any and all stop at the first answer. A generator can be used only once.
Try the code and the simulations beside the lesson.
After this lesson you can
yield,The class in the last lesson needed two methods and a lot of care. Python has a much shorter way to write an iterator: a generator. A generator is an ordinary function with one new word in it: yield.
Predict first. What type is g? Does count_to(3) print anything by itself? Then run it.
count_to(3) does not run the body. It gives a generator object. Nothing is shown.next(g) runs the body until the first yield. It gives out the value after yield (1) and pauses, with all its variables kept: i is 1.next(g) continues from where it paused: i = i + 1, the loop goes round, and the next yield gives 2.StopIteration, as for any iterator.for loop, list and sum do all this for you: list(count_to(5)) is [1, 2, 3, 4, 5], and sum(count_to(100)) is 5050.A generator is an iterator. All the rules of the last lesson hold: it is lazy, and it can be used once.
A generator is a function that can be stopped in the middle, and started again with its variables intact. A normal function can only run from the start to the end.
Because a generator makes a value only when asked, it can go on for ever.
fibonacci() is endless too. The loop at the end asks for values until one is over 1000, and then stops with break. The generator never has to know how many values you want. It is the caller who decides when to stop.
This is a strong idea: the source of the values and the use of the values are separate. The generator says how to make the next value, and the loop decides how many to take.
A comprehension with round brackets makes a generator, and not a list.
A list of squares would need all its values at once. The generator holds only where it is, so it can go on as long as you ask.
| You need | Use |
|---|---|
| a list that you will use many times, or index, or sort | a list comprehension |
| to go through the values once | a generator expression |
| a long or endless sequence | a generator function |
| a sequence with complicated steps | a generator function |
| to pass a big file through stages | generators (the project) |
list(endless_generator()). It never ends. Use islice.next.return value and expecting it to be one of the values. In a generator, return only ends it. Use yield.<generator object ...>. Convert with list to see the values, if it is finite.Start with two quick questions. Each New numbers gives you a fresh one, so you can practise as long as you like.
Then the labs and the problems:
yield is a generator. Calling it gives an iterator. next runs it to the next yield.islice takes the first few, and the loop decides when to stop.(... for ...), does not build a list. It can be used once.Try each one on your own first. If you are stuck, open a hint. Then check with Show the answer.
yield do, compared with return?sum(n * n for n in range(10 ** 7)) better than sum([n * n for n in range(10 ** 7)])?Every lesson is open to read. Enrolling also lets you:
Log in to join the discussion.
Loading…
This lesson is free to read. Enroll free to keep your place and take the tests.