Gary Herron
2/18/2008 11:53:00 PM
Brad wrote:
> Hi folks,
>
> I'm still fairly new to programming in python and programming in
> general. A friend of mine is in a CompSci 101 course and was working
> on a slider game when he encountered a problem. We eventually figured
> out what the problem was and built a test case to help solve it, but I
> can't for the life of me figure out the why behind it. I tried
> googling it and searching the list but didn't find anything that
> really explained it. I'm sure it's probably just both of us
> misunderstanding what the "while" statement does. So I hoped to ask
> for some clarification here. So here is what we worked out was going
> on with his code.
>
> from random import shuffle
>
> mylist=[2,1,3]
> baselist=[1,2,3]
> newlist=[]
> count=0
> while mylist!=baselist:
> count+=1
> shuffle(mylist)
> newlist.append(mylist)
> print count, mylist, newlist
>
> Output:
>
> 1 [3, 1, 2] [[3, 1, 2]]
> 2 [1, 2, 3] [[1, 2, 3], [1, 2, 3]]
>
>
> What he wanted was a list of lists to use later as a replay. What we
> expected newlist.append(mylist) to do was to save a copy of mylist
> into the collection for each iteration of the while statement.
> However, what struck us as odd is that for each time the while loop
> executes it changes all the lists in the list. What I found even
> exasperating was if I created yet another list.
>
> from random import shuffle
>
> mylist=[2,1,3]
> baselist=[1,2,3]
> newlist=[]
> saved_shufs=[]
> count=0
>
> while mylist!=baselist:
> count+=1
> shuffle(mylist)
> newlist.append(mylist)
> saved_shufs.append(newlist[0])
> print count, mylist, newlist[0], saved_shufs
>
> Output:
>
> 1 [1, 3, 2] [1, 3, 2] [[1, 3, 2]]
> 2 [3, 2, 1] [3, 2, 1] [[3, 2, 1], [3, 2, 1]]
> 3 [1, 2, 3] [1, 2, 3] [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>
>
> newlist[0] printed out correctly but when appending it into
> saved_shufs it still overwrote everything.
>
> Eventually, after plinking about I remembered that tuples were
> immutable and wound up creating a variable like
> tuple_of_mylist=tuple(mylist) then appending that into newlist. That
> kept the list of tuples fine. I'm still wondering though what I'm not
> grasping about "while" that made it do that to the lists? Or is it not
> even while, is it something else I'm not getting?
>
> Thanks in advance,
> B
>
First of all, it's got nothing to do with the while loop. The Python
feature that's biting you here is the fact that lists are not *copied*
when you work with them.
So in the following code, the list named full does not have 3 copies of
sub in it, but rather it has 3 *references* to the single list named
sub. Any changes to the list named sub will be reflected anywhere that
list is referred to.
>>> sub = [1,2,3]
>>> full = [sub,sub,sub]
>>> full
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> sub[0] = 123
>>> full
[[123, 2, 3], [123, 2, 3], [123, 2, 3]]
So in you code, the single list mylist is shuffled each time, and
newlist keeps growing my more references to it. If you want a *copy* of
the list, you have to explicitly ask for one. The easiest way to do
that is mylist[:]. (This is a shorthand for copying out any sublist of
mylist via the syntax mylist[a:b], with a and b defaulting to whole list.)
Gary Herron