Understanding While Loop Execution

B

Brad

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
 
G

Gary Herron

Brad said:
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
 
7

7stud

a = [1, 2, 3]
b = a
print a
print b
print

a[0] = 100
print a
print b

--output:--
[1, 2, 3]
[1, 2, 3]

[100, 2, 3]
[100, 2, 3]
 
T

Tim Roberts

Gary Herron said:
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.

Since we are being picky here, it's more accurate to say that the list
"full" contains 3 references to the list that is also referenced by the
name "sub". I've found that it is more useful to think of Python objects
(like lists) as anonymous things living out in object memory (which is, no
doubt, a happy place), and all of the names in the program just refer to
those anonymous things.
Any changes to the list named sub will be reflected anywhere that
list is referred to.

And vice versa. "sub" is a reference to the list, exactly like "full[0]".
No difference.
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]]
And:
full[0][2] = 99
sub [123, 2, 99]
full
[[123, 2, 99], [123, 2, 99], [123, 2, 99]]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,078
Latest member
MakersCBDBlood

Latest Threads

Top