24

Suppose I do the following:

>>> l = [[]]*2
>>> l
[[], []]
>>> l[0].append(1)
>>> l
[[1], [1]]

Why does 1 get appended to both lists?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Asterisk
  • 3,534
  • 2
  • 34
  • 53
  • 5
    This issue is discussed in http://docs.python.org/faq/programming.html#id38 resp. http://docs.python.org/faq/programming.html#how-do-i-create-a-multidimensional-list. – glglgl Aug 31 '11 at 10:05

4 Answers4

20

[[]]*2 is a list of two references to the same list. You are appending to it and then seeing it twice.

eumiro
  • 207,213
  • 34
  • 299
  • 261
14

Because there is really only one list. Consider this:

>>> l = [[]]
>>> l2 = l*2
>>> l2[0] is l[0]
True
>>> l2[1] is l[0]
True

*2 performed on a list does not copy the list but return a list of length 2 filled with the same reference.

What you probably wanted was this:

>>> l = [[] for _ in xrange(2)]

As @Asterisk mentions in a comment, the same behaviour is exposed by all common collections. As a rule of thumb it is therefore best to only use multiplication on immutable types with value-semantics.

blubb
  • 9,510
  • 3
  • 40
  • 82
5

Showcasing the difference with memory layout:

listOfLists = [[]] * 3
listOfListsRange = [[] for i in range(0, 3)]

run in pythontutor

memory layout shown in python tutor

Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59
user1767754
  • 23,311
  • 18
  • 141
  • 164
1

Here's how i initialize a list of lists. Rows vary slowest.

nrows = 3; ncols = 5

l_of_ls = [[0]*ncols for i in range(nrows )]

for rix, r in enumerate(l_of_ls):
    for cix, c in enumerate(r):
        print rix, cix, 'val = ',c

RESULT

0 0 val =  0
0 1 val =  0
0 2 val =  0
0 3 val =  0
0 4 val =  0
1 0 val =  0
1 1 val =  0
1 2 val =  0
1 3 val =  0
1 4 val =  0
2 0 val =  0
2 1 val =  0
2 2 val =  0
2 3 val =  0
2 4 val =  0 

Also Worth Noting for Indexing Purposes

for rix in range(nrows):
    for cix in range(ncols):
        print l_of_ls[rix][cix],
    print

RESULT

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0