250

I intend to initialize a list of list with length of n.

x = [[]] * n

However, this somehow links the lists together.

>>> x = [[]] * 3
>>> x[1].append(0)
>>> x
[[0], [0], [0]]

I expect to have something like:

[[], [0], []]

Any ideas?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Amir
  • 5,996
  • 13
  • 48
  • 61
  • Both questions reference the same code construct: `x = [ [ ] ] * n` followed by `x[ n ].append( y )` and show the same confusion over the behavior `x[ n ] == y` for all values of n. It could not more clearly be a duplicate. And yet search engine sent me here first. ;) –  Apr 24 '19 at 17:04
  • 3
    This question is about how to initialize a list of independent lists. The other question is about why the ```[ [ ] ] * n``` results in "linked" new list behavior. The answers are different, and for those seeking how to do what they want, this is the right question/answer. This is not a duplicate at all, @Loveandpeace-JoeCodeswell is right. – Greg Kramida May 16 '19 at 22:45
  • Note: this was reopened and closed solely for the purposes of fixing the old closure. Do not take my closure as an endorsement of the closure itself. – Machavity Mar 14 '21 at 02:56

1 Answers1

387

The problem is that they're all the same exact list in memory. When you use the [x]*n syntax, what you get is a list of n many x objects, but they're all references to the same object. They're not distinct instances, rather, just n references to the same instance.

To make a list of 3 different lists, do this:

x = [[] for i in range(3)]

This gives you 3 separate instances of [], which is what you want

[[]]*n is similar to

l = []
x = []
for i in range(n):
    x.append(l)

While [[] for i in range(3)] is similar to:

x = []
for i in range(n):
    x.append([])   # appending a new list!

In [20]: x = [[]] * 4

In [21]: [id(i) for i in x]
Out[21]: [164363948, 164363948, 164363948, 164363948] # same id()'s for each list,i.e same object


In [22]: x=[[] for i in range(4)]

In [23]: [id(i) for i in x]
Out[23]: [164382060, 164364140, 164363628, 164381292] #different id(), i.e unique objects this time
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
  • 3
    I've just been struggling with the same problem and my brain was nearly blown away. Your answer really helped me. – ForceBru Sep 16 '15 at 18:25
  • 12
    Use `_` instead `i` for passing "'i' value is not used" inspection. – Renat Zaripov Feb 21 '17 at 12:55
  • 1
    Spent hours debugging a script for which this behaviour was the root cause - thanks very much for the excellent answer. – otocan May 23 '17 at 09:20
  • Hi, if I want to initialize a list of lists that has no predetermined length, how can I do that without *n making all the elements the same...? – Yafim Simanovsky Dec 12 '17 at 18:07
  • Create a list containing one empty list. Keep appending an empty list to the outer list as required – inspectorG4dget Dec 14 '17 at 16:00
  • Do you think this is a bug of python or it is designed so – Albert Chen May 31 '20 at 04:57
  • This behavior has been known for a very long time. If it were a bug, I'd imagine it would have been squashed by now. I therefore believe that this is intentional – inspectorG4dget May 31 '20 at 21:56
  • 1
    This is not a bug, it is simply consistent behaviour combined with the perils of mutability. The inner `[]` is evaluated only once when writing `[[]]*n` while it is evaluated `n` times when writing `[[] for _ in range(n)]`. If you write `[1]*3` the compiler constructs a list with the object `1`, and then concatenates three copies of that list. Because `1` is immutable nothing special happens when you edit one of the items in the resulting list. However, if you replace `1` with a list you first create a list with a reference to that list, and then concatenate n copies of that list. – hugovdberg Aug 26 '20 at 12:00