Двумерные списки в Python: полное руководство
Двумерные списки в Python: создание и обработка
Двумерные списки (матрицы) представляют собой списки, элементами которых являются другие списки. Это основная структура для хранения табличных данных в Python без использования сторонних библиотек.
Основной эффективный способ: list comprehension
Для создания двумерного списка заданного размера с одинаковыми начальными значениями применяют вложенный генератор списков. Например, для матрицы 3x4 из нулей:
matrix = [[0 for j in range(4)] for i in range(3)]минимальный элемент массива python (поиск минимального элемента в массиве)
Внешний цикл for i in range(3) создаёт строки, внутренний for j in range(4) заполняет каждую строку нулями. Каждая строка создаётся независимо, поэтому изменение одного элемента не затрагивает другие строки.
Как создать двумерный список с помощью вложенных циклов?
Для начинающих может быть нагляднее явное создание пустого списка и добавление строк в цикле:
matrix = []
for i in range(3):
row = []
for j in range(4):
row.append(0)
matrix.append(row)массив python примеры (примеры массивов в python)
Этот способ даёт тот же результат, но менее компактен. Используется, когда логика заполнения сложнее и требует дополнительных условий.
Как создать список с помощью умножения и почему это может быть опасно?
Краткая запись [[0]*4]*3 создаёт три ссылки на один и тот же список строк. При изменении одного элемента меняются все строки:
matrix = [[0]*4]*3
matrix[0][0] = 5
print(matrix) # [[5,0,0,0],[5,0,0,0],[5,0,0,0]]списки в python примеры (примеры работы со списками в python)
Эта ошибка часто встречается у новичков. Правильный способ - использовать list comprehension: [[0]*4 for _ in range(3)], где внутренний список создаётся заново на каждой итерации.
Как создать зубчатый список (с разной длиной строк)?
Двумерные списки не обязаны быть прямоугольными. Строки могут иметь разную длину:
jagged = [[1,2], [3,4,5], [6]]Такой список создаётся просто перечислением вложенных списков. Доступ к элементу третьей строки: jagged[2][0] вернёт 6. При этом нужно учитывать, что не все строки имеют одинаковое количество столбцов.
Типичные ошибки при работе с двумерными списками
- IndexError при обращении по несуществующему индексу. Всегда проверяйте длину списка len(matrix) и длину строки len(matrix[i]).
- Путаница осей: часто путают строку и столбец. Помните, что первый индекс - номер строки, второй - столбца.
- Поверхностное копирование: при использовании copy.copy() или среза matrix[:] копируется только внешний список, а внутренние остаются общими. Для полного независимого копирования применяйте copy.deepcopy().
- Изменение строки через присваивание новой длины: matrix[i] = [0]*n - допустимо, но теряется старая строка.
Расширенные примеры работы с двумерными списками
Ниже приведены продвинутые примеры, демонстрирующие различные операции с матрицами.
Транспонирование матрицы
Преобразование строк в столбцы. Компактный способ через вложенный list comprehension:
matrix = [[1,2,3], [4,5,6]]
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(transposed)[[1, 4], [2, 5], [3, 6]]
Альтернатива с использованием zip и map:
transposed = list(map(list, zip(*matrix)))
print(transposed)[[1, 4], [2, 5], [3, 6]]
Функция zip(*matrix) собирает элементы с одинаковыми индексами в кортежи, а map(list, ...) преобразует их обратно в списки.
Умножение матриц
Стандартный алгоритм с тремя вложенными циклами:
def matrix_mult(A, B):
n, m = len(A), len(A[0])
p = len(B[0])
result = [[0]*p for _ in range(n)]
for i in range(n):
for j in range(p):
for k in range(m):
result[i][j] += A[i][k] * B[k][j]
return result
A = [[1,2],[3,4]]
B = [[5,6],[7,8]]
print(matrix_mult(A, B))[[19, 22], [43, 50]]
Проверьте, что количество столбцов в A равно количеству строк в B.
Обход матрицы по спирали
Вывод элементов в порядке спирали (право, вниз, лево, вверх):
def spiral_order(matrix):
if not matrix: return []
result = []
top, bottom, left, right = 0, len(matrix)-1, 0, len(matrix[0])-1
direction = 0
while top <= bottom and left <= right:
if direction == 0: # вправо
for i in range(left, right+1):
result.append(matrix[top][i])
top += 1
elif direction == 1: # вниз
for i in range(top, bottom+1):
result.append(matrix[i][right])
right -= 1
elif direction == 2: # влево
for i in range(right, left-1, -1):
result.append(matrix[bottom][i])
bottom -= 1
else: # вверх
for i in range(bottom, top-1, -1):
result.append(matrix[i][left])
left += 1
direction = (direction + 1) % 4
return result
m = [[1,2,3],[4,5,6],[7,8,9]]
print(spiral_order(m))[1, 2, 3, 6, 9, 8, 7, 4, 5]
Генерация шахматного узора
Создание матрицы с чередованием 0 и 1 как на шахматной доске:
def chessboard(rows, cols):
return [[(i+j)%2 for j in range(cols)] for i in range(rows)]
board = chessboard(5,5)
for row in board:
print(row)[0, 1, 0, 1, 0] [1, 0, 1, 0, 1] [0, 1, 0, 1, 0] [1, 0, 1, 0, 1] [0, 1, 0, 1, 0]
Сумма элементов на диагоналях
Вычисление суммы главной и побочной диагоналей квадратной матрицы:
def diagonal_sum(matrix):
n = len(matrix)
main = sum(matrix[i][i] for i in range(n))
anti = sum(matrix[i][n-1-i] for i in range(n))
return main, anti
m = [[1,2,3],[4,5,6],[7,8,9]]
print(diagonal_sum(m))(15, 15)
Поворот матрицы на 90 градусов по часовой стрелке
Комбинация транспонирования и отражения по горизонтали:
def rotate_clockwise(matrix):
n = len(matrix)
transposed = [[matrix[j][i] for j in range(n)] for i in range(n)]
rotated = [row[::-1] for row in transposed]
return rotated
m = [[1,2],[3,4]]
print(rotate_clockwise(m))[[3, 1], [4, 2]]
Глубокое копирование матрицы
Чтобы избежать случайного изменения данных при передаче в функцию, используйте copy.deepcopy:
import copy
matrix = [[1,2],[3,4]]
shallow = matrix[:]
deep = copy.deepcopy(matrix)
matrix[0][0] = 99
print('shallow:', shallow)
print('deep:', deep)shallow: [[99, 2], [3, 4]] deep: [[1, 2], [3, 4]]
Поверхностная копия (срез) копирует ссылки на внутренние списки, поэтому изменение отражается в shallow. Глубокое копирование создаёт полностью независимые объекты.