Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

List behaviour

0 views
Skip to first unread message

Gabriel

unread,
May 15, 2008, 6:08:11 AM5/15/08
to pytho...@python.org
Hi all

Just wondering if someone could clarify this behaviour for me, please?

>>> tasks = [[]]*6
>>> tasks
[[], [], [], [], [], []]
>>> 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

unread,
May 15, 2008, 6:36:34 AM5/15/08
to
Gabriel a écrit :

> Hi all
>
> Just wondering if someone could clarify this behaviour for me, please?
>
>>>> tasks = [[]]*6
>>>> tasks
> [[], [], [], [], [], []]
>>>> 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

unread,
May 15, 2008, 6:37:04 AM5/15/08
to
Gabriel wrote:

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

boc...@virgilio.it

unread,
May 15, 2008, 6:41:31 AM5/15/08
to

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

>>> tasks = [ [] for x in xrange(6) ]
>>> tasks[0].append(1)
>>> tasks
[[1], [], [], [], [], []]
>>>

Ciao
-----
FB

A.T.Hofkamp

unread,
May 15, 2008, 6:48:49 AM5/15/08
to
On 2008-05-15, Gabriel <ga...@dragffy.com> wrote:
> Hi all
>
> Just wondering if someone could clarify this behaviour for me, please?
>
>>>> tasks = [[]]*6
>>>> tasks
> [[], [], [], [], [], []]
>>>> 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

unread,
May 15, 2008, 6:50:47 AM5/15/08
to pytho...@python.org
Bruno Desthuilliers <bruno.42.desthuilliers <at> websiteburo.invalid> writes:


> 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':
>

> 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

unread,
May 15, 2008, 6:52:10 AM5/15/08
to pytho...@python.org
Diez B. Roggisch <deets <at> nospam.web.de> writes:

> 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

unread,
May 15, 2008, 6:51:27 AM5/15/08
to pytho...@python.org
<bockman <at> virgilio.it> writes:

> >>> tasks = [ [] for x in xrange(6) ]
> >>> tasks[0].append(1)
> >>> tasks
> [[1], [], [], [], [], []]
> >>>
>

Thanks, Bockman


Lie

unread,
May 15, 2008, 11:48:06 AM5/15/08
to

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).

0 new messages