Пусть даны два числа: количество строк n
и количество столбцов
m
. Необходимо создать список размером n
×m
, заполненный нулями.
Очевидное решение оказывается неверным:
A = [[0] * m ] * n
В этом легко убедиться, если присвоить элементу A[0][0]
значение 1
, а потом вывести значение другого элемента A[1][0]
— оно тоже будет равно 1! Дело в том, что
[0] * m
возвращает ccылку на список из m
нулей.
Но последующее повторение этого элемента создает список из n
элементов, которые являются ссылкой на один и тот же список (точно
так же, как выполнение операции B = A
для списков не создает
новый список), поэтому все строки результирующего списка на самом деле
являются одной и той же строкой.
Таким образом, двумерный список нельзя создавать при помощи операции повторения одной строки. Что же делать?
Первый способ: сначала создадим список из n
элементов
(для начала просто из n
нулей). Затем сделаем каждый
элемент списка ссылкой на другой одномерный список из m
элементов:
A = [0] * n
for i in range(n):
A[i] = [0] * m
Другой (но похожий) способ: создать пустой список, потом n
раз добавить в него новый элемент, являющийся списком-строкой:
A = []
for i in range(n):
A.append([0] * m)
Но еще проще воспользоваться генератором: создать список из
n
элементов, каждый из которых будет списком,
состоящих из m
нулей:
A = [[0] * m for i in range(n)]
В этом случае каждый элемент создается независимо от остальных
(заново конструируется список [0] * m
для заполнения очередного
элемента списка), а не копируются ссылки на один и тот же список.