5

I'm practicing my progamming skills by solving problems from project euler at the moment, and now I've come across some (in my opinion) strange behavior on Python.

When I do:

list = [[1]]*20

I get a list of 20 lists containing element 1, as expected. However, when I would like to append a 2 to the third element from this list, I would do that as follows:

list[3].append(2)

This however changes ALL the elements in the list. Even when I take a detour, like:

l = list[3]
l.append(2)
list[3] = l

All my elements get changed. Can anyone please tell me how to do this and get an output like so:

[[1], [1], [1], [1, 2], [1] .... [1]]

Thanks in advance.

Sander Kersten
  • 51
  • 1
  • 1
  • 2

1 Answers1

12

Python lists are mutable objects, so when you do [[1]]*20 it creates one list object [1] and then places 20 references to it in the toplevel list.

As far as the mutability problem is concerned, this is the same as the following

a = [1,2,3]
b = a
b.append(4)
a # [1,2,3,4]

This happens because b=a merely copies the reference to the list instance from a to b. They are both referring to the same actual list.

In order to create a list of lists, like you tried above, you need to create a unique list for each entry. A list comprehension works nicely:

mainlist = [[1] for x in range(20)]
mainlist[0].append(2)
mainlist # [[1,2],[1],[1],...]

Edit

As an aside, since type names are metaclasses in Python, naming your variables by the type name is a bad idea. The reason is that can cause several issues further down in the code:

a = range(3) # [0,1,2]
type(a) # (type 'list')
isinstance(a, list) # True

Now, create a variable named list

list = range(3)
list # [0,1,2]
isinstance(list, list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types

Not to mention, now you cant use the list() operator

c = list((1,2,3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
Nisan.H
  • 6,032
  • 2
  • 26
  • 26
  • Thank you very much for your quick response. I just didn't get where the bug in my program was until I found out about this curiosity. Good to know this, thank you. :) – Sander Kersten Mar 19 '13 at 22:49
  • Actually I noticed the problems mentioned in your edit earlier. This was just for the purpose of the example, won't do it again. – Sander Kersten Mar 19 '13 at 23:00
  • @SanderKersten No worries. I just figured it was worth addressing since it seems to come up every so often... I used to make that mistake in my own code every time I would play around with a small three-line function in my editor, and then copy it over into a bigger program and break everything, so I had to get myself in the habit of just never using type names for variables. – Nisan.H Mar 19 '13 at 23:03
  • My most typical downfall would be `for list in lists` or any `for in s` sort of iterator, that would keep the variable name for the entire scope in which the loop ran. – Nisan.H Mar 19 '13 at 23:04