Как создать двумерный список (матрицу) в Python?
Хочу сделать таблицу/матрицу — список списков, например сетку 3 на 3 из нулей. Попробовал [[0]*3]*3, заполнил, а у меня меняются сразу все строки! Что я делаю не так и как создать матрицу правильно?
2 ответа
Вы наткнулись на классическую ловушку. [[0]*3]*3 создаёт три ссылки на ОДИН и тот же внутренний список, поэтому изменение одной «строки» меняет все:
grid = [[0]*3]*3
grid[0][0] = 5
print(grid) # [[5,0,0],[5,0,0],[5,0,0]] — испортились все!
Внешний *3 копирует не сам список, а ссылку на него.
Правильно — создавать каждую строку отдельно через генератор списка:
rows, cols = 3, 3
grid = [[0]*cols for _ in range(rows)]
grid[0][0] = 5
print(grid) # [[5,0,0],[0,0,0],[0,0,0]] — верно!
Здесь for _ in range(rows) на каждой итерации создаёт новый список [0]*cols, поэтому строки независимы. Внутренний [0]*cols безопасен, потому что числа неизменяемы — там ловушки нет.
Обход матрицы:
for r in range(rows):
for c in range(cols):
grid[r][c] = r * cols + c
или по значениям:
for row in grid:
for value in row:
print(value, end=' ')
print()
Запомните правило: * для вложенных изменяемых объектов копирует ссылку, а не данные. Для матриц всегда используйте генератор [... for _ in range(n)].
Если матрицы большие и предстоят числовые операции (умножение, транспонирование), удобнее NumPy:
import numpy as np
grid = np.zeros((3, 3)) # матрица 3x3 из нулей
NumPy сразу даёт удобную индексацию grid[0, 1], быстрые операции над всей матрицей и никакой ловушки со ссылками. Но для учебных задач и небольших таблиц обычный список списков через генератор — самое то, без лишних зависимостей.