I was creating a grid (2 dimensional lists) of cell objects, in a nested loop. Immediately upon instantiating each cell, I have printed the values of their attributes. After exiting the loop, I loop through the cells again and re-print their attribute values. Some values seem unchanged (self.xlo), while some attributes seem to have been replaced by the attribute values (self.ylo, self.path) of the last cell. The 2 print statements are identical, and follow the same nested loop. Why are the results different?
mps = ['xxxxxx',
'xoooox',
'xoxxox',
'xoooox',
'xxxxxx']
ROWS = len(mps) # equals 5
COLS = len(mps[0]) # equals 6
SCRW = 600
SCRH = 300
CELW = int(SCRW/COLS)
CELH = int(SCRH/ROWS)
class cell():
def __init__(self, row, col, path):
self.row = row
self.col = col
self.path = path
self.xlo = int(col*CELW)
self.ylo = int(row*CELH)
return
row_blank = ['']*COLS
grid = [row_blank]*ROWS
path_list = []
for r in range(ROWS):
for c in range(COLS):
is_path = (mps[r][c]=='o')
grid[r][c] = cell(r,c, is_path)
print(f'cell {r},{c} position {grid[r][c].xlo},{grid[r][c].ylo} and path {grid[r][c].path}')
print("\n==============Re-Printing to check!")
for r in range(ROWS):
for c in range(COLS):
print(f'cell {r},{c} position {grid[r][c].xlo},{grid[r][c].ylo} and path {grid[r][c].path}')
exit()
Thanks for guidance - I seem to be making a very fundamental error with python OOP objects. Results of the print statements are below - the first set is correct , the re-print has changes.
cell 0,0 position 0,0 and path False
cell 0,1 position 100,0 and path False
cell 0,2 position 200,0 and path False
cell 0,3 position 300,0 and path False
cell 0,4 position 400,0 and path False
cell 0,5 position 500,0 and path False
cell 1,0 position 0,60 and path False
cell 1,1 position 100,60 and path True
cell 1,2 position 200,60 and path True
cell 1,3 position 300,60 and path True
cell 1,4 position 400,60 and path True
cell 1,5 position 500,60 and path False
cell 2,0 position 0,120 and path False
cell 2,1 position 100,120 and path True
cell 2,2 position 200,120 and path False
cell 2,3 position 300,120 and path False
cell 2,4 position 400,120 and path True
cell 2,5 position 500,120 and path False
cell 3,0 position 0,180 and path False
cell 3,1 position 100,180 and path True
cell 3,2 position 200,180 and path True
cell 3,3 position 300,180 and path True
cell 3,4 position 400,180 and path True
cell 3,5 position 500,180 and path False
cell 4,0 position 0,240 and path False
cell 4,1 position 100,240 and path False
cell 4,2 position 200,240 and path False
cell 4,3 position 300,240 and path False
cell 4,4 position 400,240 and path False
cell 4,5 position 500,240 and path False
==============Re-Printing to check!
cell 0,0 position 0,240 and path False
cell 0,1 position 100,240 and path False
cell 0,2 position 200,240 and path False
cell 0,3 position 300,240 and path False
cell 0,4 position 400,240 and path False
cell 0,5 position 500,240 and path False
cell 1,0 position 0,240 and path False
cell 1,1 position 100,240 and path False
cell 1,2 position 200,240 and path False
cell 1,3 position 300,240 and path False
cell 1,4 position 400,240 and path False
cell 1,5 position 500,240 and path False
cell 2,0 position 0,240 and path False
Process ended with exit code 0.
>
The problem lies in those 2 lines:
row_blank = ['']*COLS
grid = [row_blank]*ROWS
When creating a list this way, you end up with "grid" containing several references to the same row object.
The first print has "correct" values, because you print as you go. You assign initial values, print them, in the next iteration you assign new values and print them, and so on. If you separated assignments and printing the values, you'd see the problem there as well.
You can check that with this code:
for row in grid:
print(id(row))
which outputs (exact number is irrelevant, what matters is that it's the same number - which means same object):
1714813861696
1714813861696
1714813861696
1714813861696
1714813861696
Instead you should intitialise your grid like this, which ensures each row is a unique object.
grid = [['' for _ in range(COLS)] for _ in range(ROWS)]