# context not cleaned at the end of a loop containing yield?

Mensanator mensanator at aol.com
Thu Mar 26 19:59:06 CET 2009

On Mar 26, 1:34 pm, MRAB <goo... at mrabarnett.plus.com> wrote:
> TP wrote:
> > Hi everybody,
>
> > This example gives strange results:
>
> > ########
> > def foo( l = [] ):
>
> >     l2 = l
> >     print l2
> >     for i in range(10):
> >         if i%2 == 0:
> >             l2.append( i )
> >         yield i
> > ########
>
> >>>> [i for i in ut.foo()]
> > []
> > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> >>>> [i for i in ut.foo()]
> > [0, 2, 4, 6, 8]
> > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> >>>> [i for i in ut.foo()]
> > [0, 2, 4, 6, 8, 0, 2, 4, 6, 8]
> > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> > ...
>
> > How to explain this behavior? Why l is not [] when we enter again the
> > function foo()?
>
> Readhttp://www.ferg.org/projects/python_gotchas.html#contents_item_6- Hide quoted text -

So, l=[] only happens once, not everytime you call it.

Also, 12 = l means 12 is the same object and remembers it's contents
across calls
(since l is never reset).

Try this:

def foo(l=[0]):
l2 = l[1:]          # deep copy, omitting call count
print l2,l2 is l,l
l[0] += 1           # count how many times we call foo
for i in range(10):
if i%2 == 0:
l2.append(i)
yield i

>>> [i for i in foo()]
[] False [0]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [i for i in foo()]
[] False [1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [i for i in foo()]
[] False [2]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

You can see that l is not being reset to [0] on subsequent calls
and that 12 is a seperate list from l, so appending to l2 does not
change l.