3

According to the docs at https://docs.python.org/2/reference/simple_stmts.html#yield,

all local state is retained, including the current bindings of local variables, the instruction pointer, and the internal evaluation stack: enough information is saved so that the next time next() is invoked, the function can proceed exactly as if the yield statement were just another external call.

Here's a simple case:

def generator():
    my_list = range(10)
    print "my_list got assigned"
    for i in my_list:
        print i
        yield
    return

In the shell, generator() behaves like this:

>>>>generator().next()
my_list got assigned
0
>>>>generator().next()
my_list got assigned
0

I would have thought that my_list would not get reassigned each time .next() is called. Can someone explain why this happens, and why it seems like the docs contradict this?

2
  • 2
    You're creating a new generator object each time. Call next twice on the same object and you'll get the output you expect. Commented Apr 20, 2015 at 22:03
  • Almost duplicate: Generators and for loops in Python Commented Apr 20, 2015 at 22:12

3 Answers 3

9

You are creating a new generator object each time. Create one instance:

g = generator()
g.next()
g.next()

Here g references the generator object that maintains the state:

>>> def generator():
...     my_list = range(10)
...     print "my_list got assigned"
...     for i in my_list:
...         print i
...         yield
...     return
... 
>>> g = generator()
>>> g
<generator object generator at 0x100633f50>
>>> g.next()
my_list got assigned
0
>>> g.next()
1
Sign up to request clarification or add additional context in comments.

Comments

5

Yes, the generator maintains state, as you correctly found in the documentation. The problem is that in your example, you're creating two generators. The first one is not assigned to any variable, so it's discarded immediately after .next() completes. Then you create the second generator, with its own local state, that starts at the beginning.

Try this:

>>> mygen = generator()
>>> mygen.next()
my_list got assigned
0
>>> mygen.next()
1

Comments

1

You're creating a new instance of generator when you call generator(). If you instead did

my_generator = generator()
my_generator.next() # my_list got assigned, 0
my_generator.next()  # 1

the list would only be assigned once.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.