Understanding While Loop Execution

Gary Herron gherron at islandtraining.com
Mon Feb 18 18:53:08 EST 2008


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






More information about the Python-list mailing list