7

Possible Duplicate:
Unexpected feature in a Python list of lists

I want to make a list of lists in Python, but apparently this doesn't work, as changing one number changes several. Why is this, and how can I fix it?

>>> a = [[0]*3]*4
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
2
  • 3
    Dont use *. It makes copies. Use list comprehension instead Commented Oct 21, 2012 at 2:06
  • @MarkTolonen Yup, I've voted to close this question. Commented Oct 21, 2012 at 2:26

4 Answers 4

9

What you've discovered is a classic Python pitfall.

x = [0]*3 is a list. No problem there, but [x]*4 creates a list with 4 references to the exact same list x. So modifying the first element, x, also modifies the other elements as well.

Instead, if you do this:

In [193]: a = [[0]*3 for i in range(4)]

then you get 4 distinct items in the list:

In [194]: a[0][0] = 1

In [195]: a
Out[195]: [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
Sign up to request clarification or add additional context in comments.

3 Comments

StackOverflow needs the ability to bookmark an answer. This is a prime example for why.
@JonathanVanasco: Star the question.
I starred the question. I want to star the answer.
4

In Python, [x]*n creates a new list with n references to x. This is perfectly good to have if x is immutable (string, tuple, etc.), but it gets rather confusing if x is mutable since changes to one element affect x, and thus appear to affect all elements of the list.

So, the solution is to use a list comprehension to create n new things:

[x for _ in xrange(n)] # we use _ here as a "dummy variable"

In your case, it would look like

a = [[0]*3 for _ in xrange(4)]

Comments

1

Dont use *. Use list comprehension and create like:

>>> a = [[0 for i in range(3)] for j in range(4)]
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

See unutbu and nneonneo's answer for better explanation.

2 Comments

Actually, it would be nice if * made copies. The correct thing to say is that it does not make copies, only extra references.
hmm, I have read your answer; nice. Removed the statement.
-1

When using * in list's it creates copies, so when you do a[0][0]=1 all other sub-list's copy this.

In order to fix this, use a generator expression to create your list.

1 Comment

Actually, the problem is that it doesn't make copies, not that it does.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.