Unexpected behavior of list of list

K

kghose

Hi,

The following code

listoflists = [[]]*2
listoflists[0].append(1)

appends(1) to both listoflists[0] and listoflists[1] (which I did not
expect)

while

listoflists = [[]]*2
listoflists[0] = [1]
listoflists[0].append(2)

works as expected.i.e. only listoflists[0] gets 2 appended to it and
any further operations work as expected.

I can't figure out why. Any help with explaining this would be much
appreciated

thanks!
-Kaushik
 
K

kghose

Hi,

The following code

listoflists = [[]]*2
listoflists[0].append(1)

appends(1) to both listoflists[0] and listoflists[1] (which I did not
expect)

while

listoflists = [[]]*2
listoflists[0] = [1]
listoflists[0].append(2)

works as expected.i.e. only listoflists[0] gets 2 appended to it and
any further operations work as expected.

I can't figure out why. Any help with explaining this would be much
appreciated

thanks!
-Kaushik

OK, I looked at the previous few threads and I think I understand why.
I refered to this page http://www.python.org/doc/faq/programming/#how-do-i-create-a-multidimensional-list

thanks
-kaushik
 
G

Gabriel Genellina

The following code

listoflists = [[]]*2
listoflists[0].append(1)

appends(1) to both listoflists[0] and listoflists[1] (which I did not
expect)

See latest posts on this list, or read the FAQ.
 
S

Steven D'Aprano

Hi,

The following code

listoflists = [[]]*2
listoflists[0].append(1)

appends(1) to both listoflists[0] and listoflists[1] (which I did not
expect)

I think you will find the same question raised barely a few hours ago.

Hint:
list_of_lists = [[]]*2
id(list_of_lists[0]) -1211466452
id(list_of_lists[1])
-1211466452

Notice that both inner lists have the same ID? That tells you that they
are the same list.

Like about what [obj]*2 does. Does it create multiple copies of obj? No it
does not. Python never makes copies of objects unless you explicitly tell
it to.

[] on it's own creates a new empty list, so [[], []] creates a list with
two DIFFERENT empty lists in it. [[]] creates a list with one empty list
in it; *2 makes a second reference (not a copy!) of that empty list.

while

listoflists = [[]]*2
listoflists[0] = [1]
listoflists[0].append(2)

works as expected.i.e. only listoflists[0] gets 2 appended to it and
any further operations work as expected.
list_of_lists[0] = [] # creates a new empty list
id(list_of_lists[0]) -1211466228
id(list_of_lists[1]) # same ID as before
-1211466452




You know, now that Python has a warnings module, it would be really good
if list-of-lists*int raised a warning. Does anyone know if that's feasible
or possible? It needn't catch every imaginable Gotcha, just the common
case. I'm thinking something like this:

# pseudo-code
class list:
def __mul__(self, count):
for item in self:
if isinstance(item, list):
warn("this duplicates references, not copies")
break
...do the rest
 
G

Gabriel Genellina

En Fri, 09 Mar 2007 23:58:59 -0300, Steven D'Aprano
You know, now that Python has a warnings module, it would be really good
if list-of-lists*int raised a warning. Does anyone know if that's
feasible
or possible? It needn't catch every imaginable Gotcha, just the common
case. I'm thinking something like this:

# pseudo-code
class list:
def __mul__(self, count):
for item in self:
if isinstance(item, list):
warn("this duplicates references, not copies")
break
...do the rest

But isn't the same with almost any other object (except inmutable ones)?
[{}]*5, [set()]*5, even [my_instance]*5?
It's hard to tell when it's a legitimate use and when it's a mistake, and
the checking+warning call has a cost...
 

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
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top