3

I need to fill a area in a 10*10 matrix with a real number and for this i have made this code in python:

# 'x' and 'x1' are points in a surface that delimit the area
[x, x1, y, y1] = [0, 5, 0, 2]
surfaceXY = [[0]*10]*10

for i in range(x, x1):
  for j in range(y, y1):
    surfaceXY[i][j] = 5

for k in range(10):
  for l in range(10):
    print surfaceXY[k][l],
  print ""

i want to output this:

5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0

but the code will output is:

5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0

Can someone explain me why, and how is the right way to solve this problem in python?

3 Answers3

1

Note that [[0]*10]*10 does not create a list of ten lists with ten zeroes each. It creates a list with one list, with ten zeroes in it.

Since there is only one list, changes the whole column in your grid.

Use

[[0]*10 for _ in range(10)]

See 2d array of zeros for additional discussion.

Community
  • 1
  • 1
Paul Draper
  • 78,542
  • 46
  • 206
  • 285
0

The problem is with your list creation. This:

surfaceXY = [[0]*10]*10

Creates ten references to a same list, or here, all rows you're making is actually pointing to one row only. When you change one of it, all of them is modified. Thus the result you are having.

To solve this, one would use this:

surfaceXY = [[0 for _ in range(10)] for _ in range(10)]

Or alternatively:

surfaceXY = [[0]*10 for _ in range(10)]

Here's my run with your modified code :)

>>> surfaceXY = [[0 for _ in range(10)] for _ in range(10)]
>>> for i in range(x, x1):
  for j in range(y, y1):
    surfaceXY[i][j] = 5


>>> for k in range(10):
  for l in range(10):
    print (surfaceXY[k][l], end=' ')
  print('', end='\n')


5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
aIKid
  • 26,968
  • 4
  • 39
  • 65
0

For me it looks like each of the rows have the same id (memory location) meaning they are the same data structure.

>>> id(surfaceXY[0])
4548151416
>>> id(surfaceXY[1])
4548151416

So this means that the mult operator of a list makes a copy of the pointer and not a copy of the data.

Try this initializer:

surfaceXY = [[0]*10 for i in range(10)]

Test:

>>> [x, x1, y, y1] = [0, 5, 0, 2]
>>> surfaceXY = [[0]*10 for i in range(10)]
>>> for i in range(x, x1):
...   for j in range(y, y1):
...     surfaceXY[i][j] = 5
... 
>>> for k in range(10):
...   for l in range(10):
...     print surfaceXY[k][l],
...   print ""
... 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
5 5 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
>>> 
Matt Williamson
  • 39,165
  • 10
  • 64
  • 72