Question about yield

Steven D'Aprano steve at pearwood.info
Mon Nov 16 08:10:20 EST 2015


On Sun, 15 Nov 2015 01:37 pm, fl wrote:

> Hi,
> I have read a couple of tutorial on yield. The following code snippet
> still gives me a shock. I am told yield is a little like return. I only
> see one yield in the tutorial examples. Here it has two yields. And there
> are three variables following keyword yield.

Correct. `yield` exits the running function, but unlike `return`, the
function doesn't close down, it just pauses, ready to start up again when
you call next() on it.

Here is an example of an ordinary function:

py> def function():
...     return 1
...     return 2
...     return 3
...
py> function()
1
py> function()
1

Each time you call the function, it starts again at the beginning, and exits
after the first `return`. So the lines `return 2` and `return 3` are dead
code that never gets run.

Here is an example of a generator function with yield. Calling generators is
a bit different from calling a function: first you have to initialise them
by calling the function to create a "generator object", then you call the
next() function to advance to the next `yield` statement, and finally they
raise an exception when there are no more `yields`.

An example might help:

py> def generator():
...     yield 1
...     yield 2
...     yield 3
...
py> gen = generator()
py> next(gen)
1
py> next(gen)
2
py> next(gen)
3
py> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


To start the generator from the beginning again, you have to create a new
generator object by calling the function:

gen = generator()


Calling next() many times is often inconvenient. Normally you will iterate
over the generator:

for x in gen:
    print(x)

or you call collect all the items using list(). See example below.

Here is a generator which takes a list as argument, and returns a running
sum of the list values:

def running_sum(alist):
    total = 0
    for value in alist:
        total += value
        yield total


And here is an example of using it:

py> gen = running_sum(data)
py> list(gen)
[1, 3, 6, 16, 18, 18, 23]



-- 
Steven




More information about the Python-list mailing list