# strange list comprehension on generator

Discussion in 'Python' started by Roland Puntaier, Aug 29, 2007.

1. ### Roland PuntaierGuest

def changeOne(aa,idx):
aa[idx]=not aa[idx]
yield aa
for i in range(idx):
for x in changeOne(aa,i):
yield x

def changeOneOrder(aa):
yield aa
for i in range(len(aa)):
for x in changeOne(aa,i):
yield x

a=[False]*3
og=changeOneOrder(a)
#this does not return the way I would expect. why?
list(og)
#returns
#[[False, False, True], [False, False, True], [False, False, True],
[False, False, True], [False, False, True], [False, False, True], [False,
False, True], [False, False, True]]

#this works as expected
a=[False]*3
og=changeOneOrder(a)
og.next()
og.next()
....

#this works as expected
def ty():
yield 1
yield 2
yield 3

tg=ty()
list(tg)

cheers, Roland

Roland Puntaier, Aug 29, 2007

2. ### Bjoern SchliessmannGuest

No greeting, no text? Pity.

Roland Puntaier wrote:

> def changeOne(aa,idx):
> aa[idx]=not aa[idx]
> yield aa
> for i in range(idx):
> for x in changeOne(aa,i):
> yield x
>
> def changeOneOrder(aa):
> yield aa
> for i in range(len(aa)):
> for x in changeOne(aa,i):
> yield x

Okay, two generator definitions.

> a=[False]*3
> og=changeOneOrder(a)
> #this does not return the way I would expect. why?

What do you expect? You created a generator object and bound it
to "og".

Please always state what you expect and what really happens. Fortune
telling is not one of my hobbies (and I think I'm not alone with
that).

Regards,

Björn

--
BOFH excuse #284:

Electrons on a bender

Bjoern Schliessmann, Aug 29, 2007

3. ### =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=Guest

> #this does not return the way I would expect. why?

You yield the very same list object all the times. So
when you make a later change, all earlier results will
get changed, too (since they are the same object).
Of course, it won't affect the terminal output, so you
don't see that the older values changed in the example
that you think works as expected.

HTH,
Martin

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=, Aug 29, 2007
4. ### =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=Guest

> #this does not return the way I would expect. why?

You yield the very same list object all the times. So
when you make a later change, all earlier results will
get changed, too (since they are the same object).
Of course, it won't affect the terminal output, so you
don't see that the older values changed in the example
that you think works as expected.

HTH,
Martin

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=, Aug 29, 2007
5. ### Guest

On Aug 29, 6:50 am, Roland Puntaier <Roland.Punta...@br-
automation.com> wrote:
> def changeOne(aa,idx):
> aa[idx]=not aa[idx]
> yield aa
> for i in range(idx):
> for x in changeOne(aa,i):
> yield x
>
> def changeOneOrder(aa):
> yield aa
> for i in range(len(aa)):
> for x in changeOne(aa,i):
> yield x
>
> a=[False]*3
> og=changeOneOrder(a)
> #this does not return the way I would expect. why?
> list(og)
> #returns
> #[[False, False, True], [False, False, True], [False, False, True],
> [False, False, True], [False, False, True], [False, False, True], [False,
> False, True], [False, False, True]]

If you want the "intermediate" states of 'a' in
list(og), then you need to yield a copy of that list,

def changeOne(aa, idx):
aa[idx] = not aa[idx]
yield aa[:] # <------- a copy
for i in range(idx):
for x in changeOne(aa, i):
yield x

def changeOneOrder(aa):
yield aa[:] # <------- a copy
for i in range(len(aa)):
for x in changeOne(aa, i):
yield x

a = [False] * 3
og = changeOneOrder(a)
print list(og)

Otherwise, as you've already noticed, you can
loop over the iterator and do something
with the "instantaneous" state of 'a'.

--
Hope this helps,
Steven

, Aug 29, 2007