2

I recently tried to instantiate a 4x4 constant (0's) array by using

a = [[0] * 4] * 4

which instantiates the array a as

[[0, 0, 0, 0], 
 [0, 0, 0, 0], 
 [0, 0, 0, 0], 
 [0, 0, 0, 0]]

However, this does not create an array of unique elements as altering an element in any of the arrays changes all of them, e.g.:

a[0][0] = 1

alters a to

[[1, 0, 0, 0], 
 [1, 0, 0, 0], 
 [1, 0, 0, 0], 
 [1, 0, 0, 0]]

I think I understand why this happens (copies of lists copy the list's pointer and do not create separate copies unless specified, unlike int's, etc.) but am left wondering:

Is there any quick and easy way to instantiate a constant array (without using any external modules, such as NumPy) with unique elements that can later be altered by simple a[i][j] = x addressing?

SLesslyTall
  • 261
  • 1
  • 3
  • 8

2 Answers2

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

should do it, it'll create separate lists

maor10
  • 1,645
  • 18
  • 28
2

Just for free. What is going on here ? When one does

>>> a = [[0] * 4] * 4

first, one creates one list [0] * 4 with four 0 elements. Let call this list li.

Then when you do [li] * 4, one actually creates a list which refers four times to the same object. See

>>> [id(el) for el in a]
[8696976, 8696976, 8696976, 8696976] # in my case

Whence the (not that) curious result one gets when entry-wise assigning like so

>>> a[0][0] = 1
[[1, 0, 0, 0], 
 [1, 0, 0, 0], 
 [1, 0, 0, 0], 
 [1, 0, 0, 0]]

A solution is simply to ensure that each element of the list really is unique. For example doing

#Python2
>>> a = map(lambda _: [0]*4, range(4))
#Python3
>>> a = list(map(lambda _: [0]*4, range(4)))
#Python2&3
>>> a[0][0] = 1
[[1, 0, 0, 0], 
 [0, 0, 0, 0], 
 [0, 0, 0, 0], 
 [0, 0, 0, 0]]
keepAlive
  • 6,369
  • 5
  • 24
  • 39