Connecting Tech Pros Worldwide Forums | Help | Site Map

List behaviour

Gabriel
Guest
 
Posts: n/a
#1: Jun 27 '08
Hi all

Just wondering if someone could clarify this behaviour for me, please?
Quote:
Quote:
Quote:
>>tasks = [[]]*6
>>tasks
[[], [], [], [], [], []]
Quote:
Quote:
Quote:
>>tasks[0].append(1)
>>tasks
[[1], [1], [1], [1], [1], [1]]

Well what I was expecting to end up with was something like:
>>tasks
[[1], [], [], [], [], []]


I got this example from page 38 of Beginning Python.

Regards

Gabriel




Bruno Desthuilliers
Guest
 
Posts: n/a
#2: Jun 27 '08

re: List behaviour


Gabriel a écrit :
Quote:
Hi all
>
Just wondering if someone could clarify this behaviour for me, please?
>
Quote:
Quote:
>>>tasks = [[]]*6
>>>tasks
[[], [], [], [], [], []]
Quote:
Quote:
>>>tasks[0].append(1)
>>>tasks
[[1], [1], [1], [1], [1], [1]]
>
Well what I was expecting to end up with was something like:
>>tasks
[[1], [], [], [], [], []]
The problem here is that your first statement

#>>tasks = [[]]*6

creates a list (task) containing 6 references to the *same* (empty) list
object. You can check this easily using the identity test operator 'is':

#>>tasks[0] is tasks[1]
True


In fact, it's exactly as if you had written:

#>>task = []
#>>tasks = []
#>>for i in range(6):
#... tasks.append(task)
#...

If you want 6 different list objects in tasks, you can use a list
comprehension instead:

#>>tasks = [[] for i in range(6)]
#>>tasks
[[], [], [], [], [], []]
#>>tasks[0].append(1)
#>>tasks
[[1], [], [], [], [], []]

HTH
Diez B. Roggisch
Guest
 
Posts: n/a
#3: Jun 27 '08

re: List behaviour


Gabriel wrote:
Quote:
Hi all
>
Just wondering if someone could clarify this behaviour for me, please?
>
Quote:
Quote:
>>>tasks = [[]]*6
>>>tasks
[[], [], [], [], [], []]
Quote:
Quote:
>>>tasks[0].append(1)
>>>tasks
[[1], [1], [1], [1], [1], [1]]
>
Well what I was expecting to end up with was something like:
>>tasks
[[1], [], [], [], [], []]
>
>
I got this example from page 38 of Beginning Python.
The "problem" is that all the lists inside the outer list are the same
list - you can check that with

id(tasks[0]) == id(tasks[1])

So instead of creating a list of list by the *-operator that only multiplies
the references (which is fine immutable objects like strings or numbers),
you need to explicitly create new lists, e.g. with a list-comprehension:

tasks = [[] for _ in xrange(6)]

Try this and everything will work as expected.

Diez
bockman@virgilio.it
Guest
 
Posts: n/a
#4: Jun 27 '08

re: List behaviour


On 15 Mag, 12:08, Gabriel <g...@dragffy.comwrote:
Quote:
Hi all
>
Just wondering if someone could clarify this behaviour for me, please?
>
Quote:
Quote:
>tasks = [[]]*6
>tasks
>
[[], [], [], [], [], []]>>tasks[0].append(1)
Quote:
Quote:
>tasks
>
[[1], [1], [1], [1], [1], [1]]
>
Well what I was expecting to end up with was something like:
>>tasks
[[1], [], [], [], [], []]
>
I got this example from page 38 of Beginning Python.
>
Regards
>
Gabriel
The reason is that
tasks = [[]]*6
creates a list with six elements pointing to *the same* list, so when
you change one,
it shows six times.

In other words, your code is equivalent to this:
Quote:
Quote:
Quote:
>>a = []
>>tasks = [a,a,a,a,a,a]
>>a.append(1)
>>tasks
[[1], [1], [1], [1], [1], [1]]


Insead, to create a list of lists, use the list comprehension:
Quote:
Quote:
Quote:
>>tasks = [ [] for x in xrange(6) ]
>>tasks[0].append(1)
>>tasks
[[1], [], [], [], [], []]
Quote:
Quote:
Quote:
>>>
Ciao
-----
FB
A.T.Hofkamp
Guest
 
Posts: n/a
#5: Jun 27 '08

re: List behaviour


On 2008-05-15, Gabriel <gabe@dragffy.comwrote:
Quote:
Hi all
>
Just wondering if someone could clarify this behaviour for me, please?
>
Quote:
Quote:
>>>tasks = [[]]*6
>>>tasks
[[], [], [], [], [], []]
Quote:
Quote:
>>>tasks[0].append(1)
>>>tasks
[[1], [1], [1], [1], [1], [1]]
>
Well what I was expecting to end up with was something like:
?>>tasks
[[1], [], [], [], [], []]
>
>
I got this example from page 38 of Beginning Python.
This is a more complicated case of

a = []
b = a

a.append(1)
print b # Will print "[1]"

This is the case, because both a and b refer to the same list data-value.


In your case, basically what you are doing is

a = [] # a is an empty list (introduced for easier explanation)
tasks = [a] # tasks is a list with 1 'a'
tasks = tasks*6 # you create 5 additional references to 'a' in 'tasks

ie tasks is now the equivalent of [a, a, a, a, a, a]. It refers to the same 'a'
list 6 times. When you print 'tasks', you actually print the same 'a' value 6
times.


in particular, tasks is **NOT**

a,b,c,d,e,f = [], [], [], [], [], [] # create 6 different empty list values
tasks2 = [a, b, c, d, e, f]

although when you print both tasks, you won't see the difference.


Next, 'tasks[0]' refers to the first list element, that is, value 'a'. To that
list you append an element. In other words, you do "a.append(1)".

However, since tasks has 6 references to the same list 'a', all its members
appear to be changed (but you are really displaying the same value 6 times).


You can query this equality with 'is':

print tasks[0] is tasks[1] # will print 'True'
print tasks2[0] is tasks2[1] # Will print 'False'


Sincerely,
Albert
Gabriel
Guest
 
Posts: n/a
#6: Jun 27 '08

re: List behaviour


Bruno Desthuilliers <bruno.42.desthuilliers <atwebsiteburo.invalidwrites:

Quote:
The problem here is that your first statement
>
#>>tasks = [[]]*6
>
creates a list (task) containing 6 references to the *same* (empty) list
object. You can check this easily using the identity test operator 'is':
>
Quote:
If you want 6 different list objects in tasks, you can use a list
comprehension instead:
>
#>>tasks = [[] for i in range(6)]
#>>tasks
[[], [], [], [], [], []]
#>>tasks[0].append(1)
#>>tasks
[[1], [], [], [], [], []]
>
HTH
--
http://mail.python.org/mailman/listinfo/python-list
Hi Bruno

Thanks for clearing that up. Your example certainly works well, I will study
list comprehension a little more.

Many thanks

Gabriel




Gabriel
Guest
 
Posts: n/a
#7: Jun 27 '08

re: List behaviour


Diez B. Roggisch <deets <atnospam.web.dewrites:
Quote:
So instead of creating a list of list by the *-operator that only multiplies
the references (which is fine immutable objects like strings or numbers),
you need to explicitly create new lists, e.g. with a list-comprehension:
>
tasks = [[] for _ in xrange(6)]
>
Try this and everything will work as expected.
>
Thanks, Diez.

Thanks to all who replied to help me with this :)

Gabriel
Guest
 
Posts: n/a
#8: Jun 27 '08

re: List behaviour


<bockman <atvirgilio.itwrites:
Quote:
Quote:
Quote:
>tasks = [ [] for x in xrange(6) ]
>tasks[0].append(1)
>tasks
[[1], [], [], [], [], []]
Quote:
Quote:
>>
>
Thanks, Bockman


Lie
Guest
 
Posts: n/a
#9: Jun 27 '08

re: List behaviour


On May 15, 5:08Â*pm, Gabriel <g...@dragffy.comwrote:
Quote:
Hi all
>
Just wondering if someone could clarify this behaviour for me, please?
>
Quote:
Quote:
>tasks = [[]]*6
>tasks
>
[[], [], [], [], [], []]>>tasks[0].append(1)
Quote:
Quote:
>tasks
>
[[1], [1], [1], [1], [1], [1]]
>
Well what I was expecting to end up with was something like:
>>tasks
[[1], [], [], [], [], []]
>
I got this example from page 38 of Beginning Python.
>
Regards
>
Gabriel
As a complementary note, if you want to copy a list (probably a filled
one instead of blank ones like here) and wanted to copy a list so that
the new copy is a completely separate instance from the old copy, you
may use deepcopy (from copy import deepcopy).
Closed Thread