1

I have written the following code in a programming exercise:

q = lenP[0]*[lenP[1]*[0.]] # empty 2D array
for i in range(lenP[0]):
    for j in range(lenP[1]):
        hit = (Z == colors[i][j])
        q[i][j] = (hit * sensor_right + (1-hit) * (1.-sensor_right)) * p[i][j]

The value of every element q[i][j] is correctly set if I test for it inside the loop. But, if I print any q[i][j] outside of the loop, it has reverted to its initial value of 0. I think I have missed something in the management of python references to object, but what would that be ?

In a normal setting I would have used numpy for the array and be done with it, but this is a code for an Udacity course (IA for Robotics, very interesting by the way) and one is not allowed to import anything.

vkubicki
  • 1,104
  • 1
  • 11
  • 26
  • You didn't know that the problem is actually in the first line of code here, but questions with the exact same cause of problem have cropped up many, many times. – Oleh Prypin May 25 '13 at 18:59
  • Thank you for pointing to the other question. This is not the first time I face this problem, but it is always disguised in a new form :). – vkubicki May 25 '13 at 19:33

1 Answers1

5

There's sharing here between all your rows. I minimize your example:

q = 2 * [ 2 * [0] ]
for i in range(2):
   for j in range(2):
       q[i][j] = (1-i) * j
       print(q)

You'll see that every time we redefine the same row:

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

The good version would be to define a real matrix without sharing by using

q = [ [ 0 for j in range(2) ] for i in range(2) ]

or any other idiom with a guarantee of independence between rows.

Of course, with simple construction like this, you can drop the for loops:

q = [ [ (1-i) * j for j in range(2) ] for i in range(2) ]
deufeufeu
  • 998
  • 5
  • 11
  • And it would be even better to calculate the matrix while building it. Instead of creating and overwriting it. – Achim May 25 '13 at 18:59
  • @Achim: Yes, you're right I've completed my answer accordingly. Thank you. – deufeufeu May 25 '13 at 19:00
  • As I get it, each row is a reference to the same list object, and as it is a list, it is mutable, so the same content is changed each time. But, inside a row, the objects pointed to are immutable, and therefore can be different. Right ? – vkubicki May 25 '13 at 19:32
  • Yes everything besides numeric types is stored by reference in Python variable. When the type is immutable, there's no side effect, but when it isn't you can have this behavior. You'll have the same issue soon when trying to copy a matrix by assigning it to another variable... Try looking at copy.deepcopy in the Python library. – deufeufeu May 25 '13 at 19:37