3

The following Code in python:

matrix = [[0]*3]*2
matrix[0][1] = 1

seeems to be changing the value at all the matrix[][1]th positions, matrix becomes [[0,1,0],[0,1,0]] instead of [[0,1,0],[0,0,0]].

Is this a problem with how the variable is initialised or is the default behaviour in python.

Also How do I change only one value at a time.

dMb
9,3953 gold badges50 silver badges66 bronze badges
asked Nov 23, 2011 at 9:46

2 Answers 2

6

There are some subtleties on how the multiplication operator * works on lists in python.

More generally, there are differences on its effects when applied on immutable objects such integers or strings, and how those it has when applied on mutable objects like lists and dictionaries.

This might clarify the issue:

>>> l = [0] * 3 #a list of immutable integers
>>> l
[0, 0, 0]
>>> l[0] = 1
>>> l
[1, 0, 0]
>>> l = [[0]] * 3 #a list of mutable lists
>>> l
[[0], [0], [0]]
>>> l[0][0] = 1
>>> l
[[1], [1], [1]]

EDIT (kudos to @lazyr in the comments) Under the hood, in both cases the * operator creates a list of objects with the same identity (memory address), so each number (and each list) in the array are really the same object, however, immutable types can not be modified but only replaced, so when you try to assign a new value to the integer array, you will factually replace the entire object, while this is not the case with lists. Bulding on the previous example (keep in mind that the id function returns the object's memory address):

>>> m = [1] * 3
>>> id(m[0])
39356344
>>> id(m[1])
39356344
>>> m[1] = 2
>>> id(m[1])
39356320 # new memory addres = different object!
>>> m = [[1]] * 3
>>> id(m[0])
40275408
>>> id(m[1])
40275408
>>> m[1][0] = 2
>>> id(m[1])
40275408 # same memory address = still the same object!

So, in your case a possible workaround would be to initialise the matrix like this:

>>> matrix = [[0 for i in range(3)] for j in range(2)]
>>> matrix
[[0, 0, 0], [0, 0, 0]]
>>> matrix[0][2] = 1
>>> matrix
[[0, 1, 0], [0, 0, 0]]

An alternative - more radical - way would be to altogether switch to numpy, which is faster and thought from the ground up for extremely fast matrix and multidimensional vectors manipulation, but it is also harder to use.

HTH!

answered Nov 23, 2011 at 9:53
Sign up to request clarification or add additional context in comments.

4 Comments

I get it.. Thanks Mac!! Its a poor way of initialising a list of list then, read this in some python notes explaining matrices in python.
Nice explanation. Much much better than my attempt ;)
As I've understood this, there is in fact no difference in how * operates on mutable and immutable types. In both cases it creates a list of objects with the same identity (memory address). The difference lies in the modification that happens later: immutable types can not be modified but only replaced, so you only see this effect on mutable types.
It's a fine way to initialize lists if you know what you're getting in to. Sometimes having multiple references to the same object in a list is exactly what you want (at least to start).
3

Try:

matrix = [[0]*3 for j in xrange(2)]
answered Nov 23, 2011 at 9:54

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.