This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Generator mangles returned lists.
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: edw, rhettinger
Priority: normal Keywords:

Created on 2004-06-13 03:56 by edw, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (3)
msg21175 - (view) Author: Ed Watkeys (edw) Date: 2004-06-13 03:56
I have run into what seems like a bug. Check this out...

def gen():
        l = []
        l.append('eggs')
        l = l[-1:]
        yield l
        l.append('ham')
        l = l[-1:]
        yield l

>>> [i for i in gen()]
[['eggs', 'ham'], ['ham']]

>>> g = gen(); [g.next(), g.next()]
[['eggs', 'ham'], ['ham']]

>>> g = gen(); g.next(); g.next()
['eggs']
['ham']

>>> g = gen(); i = g.next(); j = g.next(); [i,j]
[['eggs', 'ham'], ['ham']]

>>> g = gen(); [g.next()[:], g.next()[:]]
[['eggs'], ['ham']]

Anyone have any insight into this?
msg21176 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-06-13 04:20
Logged In: YES 
user_id=80475

Sorry, this isn't a bug.  You've created a cute example of
the joys of mutability.

For some fun, post this on comp.lang.python and expect some
lively results.

Essentially the issue is that that the first yield is
returns a mutable list.  If printed right away, it will show
its then current value of ['eggs'].  Upon restarting the
generator, the list is updated to ['ham', 'eggs'] which is
what prints for the *first* list return value (it is still
the same list with changed contents).

When 'l' is re-assigned with " l = l[-1:]", the original
list is still intact while the value assigned to "l" changes
to be a new list (the slice).  So you have the original list
modified and the new list with a different value.  Very cute.

If none of this is clear to you, try wrapping the output
with the id() function to see which object is being displayed:

[id(i) for i in gen()]
g=gen(); [id(g.next()), id(g.next())]
msg21177 - (view) Author: Ed Watkeys (edw) Date: 2004-06-13 04:58
Logged In: YES 
user_id=44209

Ah. I get it. I guess it's time to pull out copy.copy().
History
Date User Action Args
2022-04-11 14:56:04adminsetgithub: 40392
2004-06-13 03:56:37edwcreate