Я думаю, это потому, что python использует слабую копию списка, когда вы вызываете
grid = [...] * nrows
Я пытался жестко кодировать список, и он работал правильно:
>>> grid = [[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]]
>>> for r in range(nrows):
... for c in range(ncols):
... grid[r][c] = int(random() * 100)
...
>>> pprint(grid)
[[67, 40, 41, 50, 92],
[26, 42, 64, 77, 77],
[65, 67, 88, 77, 76],
[36, 21, 41, 29, 25],
[98, 77, 38, 40, 96]]
Этоговорит мне, что когда python копирует список 5 раз, все, что он делает, это сохраняет 5 указателей на ваш первый список - затем, когда вы изменяете значения в этом списке, вы на самом деле просто меняете значение в первом списке, и это отражаетсяво всех списках, которые указывают на это.
Используя ваш метод, вы не можете обновлять весь список независимо.
Вместо этого я бы предложил изменить строку генерации списка, чтобы она выглядела больше так:
grid = [[0] * ncols for row in range(ncols)]
Это должно создать для вас 5 независимых списков.