Django-Admin.ru

Двумерный массив (список списков) в Python

Двумерный массив в Python как список списков: создание матрицы, ввод с клавиатуры, вывод, обход, транспонирование через zip, поиск, сортировка и копирование.

Редакция Django-Admin.ru
· 22 мин чтения

Содержание · 15 разделов
  1. Как устроен двумерный массив в Python
  2. Как создать двумерный массив
  3. Вручную
  4. Заполненный нулями: генератор списка
  5. Ловушка [[0] * m] * n
  6. Заполнение по формуле
  7. Пустой массив и добавление строк
  8. Ввод матрицы с клавиатуры
  9. Размеры в первой строке, затем n строк по m чисел
  10. Каждый элемент на отдельной строке
  11. Все числа в одной строке
  12. Быстрый ввод через sys.stdin
  13. Поле из символов
  14. Проверка ввода
  15. Как вывести двумерный массив
  16. Обход двумерного массива
  17. По строкам
  18. По столбцам
  19. По диагоналям
  20. Соседи клетки
  21. Транспонирование: zip(*matrix)
  22. Поворот и отражение матрицы
  23. Поиск элемента
  24. Сумма элементов: по строкам, столбцам и диагоналям
  25. Сортировка двумерного массива
  26. Добавление и удаление строк и столбцов
  27. Копирование: copy, срезы и deepcopy
  28. NumPy-массив или список списков
  29. Частые ошибки
  30. IndexError: list index out of range
  31. Числа остались строками
  32. Все строки меняются одновременно
  33. Частые вопросы
  34. Как узнать размер двумерного массива?
  35. Как превратить двумерный массив в одномерный?
  36. Как создать трёхмерный массив?
  37. Как сохранить матрицу в файл и прочитать обратно?
  38. Как перемножить две матрицы без NumPy?
  39. Чем двумерный массив отличается от списка кортежей или словаря?
  40. Итог

Двумерный массив в Python — это список списков: внешний список хранит строки, каждая строка — отдельный список значений. Матрицу из n строк и m столбцов, заполненную нулями, создают генератором [[0] * m for _ in range(n)], а к элементу обращаются двумя индексами: matrix[i][j], где i — номер строки, j — номер столбца.

n, m = 3, 4
matrix = [[0] * m for _ in range(n)]
matrix[1][2] = 7
print(matrix)        # → [[0, 0, 0, 0], [0, 0, 7, 0], [0, 0, 0, 0]]
print(matrix[1][2])  # → 7

Ниже — создание и главная ловушка [[0] * m] * n, ввод матрицы в форматах школьных и олимпиадных задач, вывод, обход по строкам, столбцам и диагоналям, транспонирование, поиск, суммы, сортировка, копирование и переход на NumPy. Примеры проверены на Python 3.12. Методы обычного списка разобраны в статье про списки в Python.

Как устроен двумерный массив в Python

Отдельного типа «двумерный массив» в Python нет. Матрица — это list, элементы которого тоже list. Поэтому matrix[0] возвращает целую строку, а matrix[0][2] — элемент этой строки.

matrix = [
    [1, 2, 3],
    [4, 5, 6],
]
print(matrix[0])      # → [1, 2, 3]
print(matrix[1][0])   # → 4
print(matrix[-1][-1]) # → 6 (последний элемент последней строки)
print(len(matrix), len(matrix[0]))  # → 2 3 (строк и столбцов)
Что нужноВыражениеРезультат
Элементmatrix[i][j]одно значение
Строкаmatrix[i]список
Столбец[row[j] for row in matrix]новый список
Часть строкиmatrix[i][1:3]срез строки
Число строк и столбцовlen(matrix), len(matrix[0])два целых числа
Главная диагональ[matrix[i][i] for i in range(n)]список

Строки могут быть разной длины — такой «рваный» массив (jagged array) Python не запрещает. Многие приёмы ниже, например len(matrix[0]) как число столбцов, рассчитаны на прямоугольную матрицу.

Как создать двумерный массив

Вручную

Небольшую матрицу с известными значениями записывают литералом — по строке на каждую строку матрицы, как в примере выше.

Заполненный нулями: генератор списка

Стандартный способ создать матрицу n × m — генератор списка (list comprehension), который на каждой итерации строит новую строку:

n, m = 3, 4
matrix = [[0] * m for _ in range(n)]

Внутреннее [0] * m безопасно: умножение копирует ссылки на неизменяемое число 0. Вместо 0 подставьте любое значение: None, "", False, "." для игрового поля.

Ловушка [[0] * m] * n

Короткая запись [[0] * m] * n выглядит правильно, но создаёт n ссылок на один и тот же список-строку. Изменение одной строки видно во всех:

n, m = 3, 4
bad = [[0] * m] * n
bad[0][0] = 5
print(bad)              # → [[5, 0, 0, 0], [5, 0, 0, 0], [5, 0, 0, 0]]
print(bad[0] is bad[1]) # → True

good = [[0] * m for _ in range(n)]
good[0][0] = 5
print(good)               # → [[5, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
print(good[0] is good[1]) # → False

Оператор * повторяет ссылки на объект и не создаёт копий. Эта ошибка разобрана и в официальном FAQ Python — раздел How do I create a multidimensional list?.

Важно: если матрица «сама» меняет соседние строки, первым делом проверьте, как она создана. Та же проблема возникает при matrix.append(row) в цикле, если row создан один раз до цикла.

Заполнение по формуле

Во вложенном генераторе значение может зависеть от номера строки i и столбца j:

n, m = 3, 4
table = [[i * j for j in range(m)] for i in range(n)]
print(table)     # → [[0, 0, 0, 0], [0, 1, 2, 3], [0, 2, 4, 6]]

numbers = [[i * m + j + 1 for j in range(m)] for i in range(n)]
print(numbers)   # → [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

identity = [[int(i == j) for j in range(3)] for i in range(3)]
print(identity)  # → [[1, 0, 0], [0, 1, 0], [0, 0, 1]]

Внешний for перебирает строки, внутренний — столбцы. Порядок важен: [[... for j in range(m)] for i in range(n)] даёт n строк по m элементов.

Случайная матрица для тренировки:

import random

grid = [[random.randint(1, 9) for _ in range(4)] for _ in range(3)]
print(grid)  # → например, [[3, 2, 5, 2], [8, 8, 8, 7], [4, 2, 8, 1]]

Пустой массив и добавление строк

Если размер заранее неизвестен, начните с пустого списка и добавляйте строки методом append:

matrix = []
matrix.append([1, 2, 3])
matrix.append([4, 5, 6])
print(matrix)  # → [[1, 2, 3], [4, 5, 6]]

empty = [[] for _ in range(3)]  # три пустые строки
empty[0].append("x")
print(empty)   # → [['x'], [], []]

Ввод матрицы с клавиатуры

Ввод почти всегда строится одинаково: прочитать строку через input(), разбить её методом split() и превратить части в числа через int или map(). Разница — в том, как размеры и числа расположены во входных данных.

Размеры в первой строке, затем n строк по m чисел

Самый частый формат задач:

3 4
1 2 3 4
5 6 7 8
9 10 11 12
n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(n)]
print(matrix)  # → [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

Если размеры стоят на отдельных строках, замените первую строку на n = int(input()) и m = int(input()). Число столбцов при таком вводе часто не нужно: каждая строка разбивается целиком.

Тот же ввод с подсказками для пользователя:

n = int(input("Сколько строк? "))
matrix = []
for i in range(n):
    row = input(f"Строка {i + 1}: ").split()
    matrix.append([int(x) for x in row])
print(matrix)

Каждый элемент на отдельной строке

В части курсов размеры даются двумя числами, а затем идут n × m элементов — по одному на строку, сначала первая строка матрицы, потом вторая:

2
3
кот
пёс
ёж
сыр
хлеб
чай
n = int(input())
m = int(input())
matrix = [[input() for _ in range(m)] for _ in range(n)]
for row in matrix:
    print(*row)
кот пёс ёж
сыр хлеб чай

Частая ошибка в этой задаче — писать matrix = [...] внутри цикла: каждая итерация перезаписывает матрицу, и остаётся только последняя строка. Строку нужно добавлять: matrix.append([...]).

Все числа в одной строке

Если после размеров все n × m чисел идут одной строкой, прочитайте их плоским списком и нарежьте срезами по m:

n, m = map(int, input().split())          # 2 3
flat = list(map(int, input().split()))    # 1 2 3 4 5 6
matrix = [flat[i * m:(i + 1) * m] for i in range(n)]
print(matrix)  # → [[1, 2, 3], [4, 5, 6]]

Быстрый ввод через sys.stdin

На олимпиадах и в задачах с большой матрицей числа могут быть разбиты по строкам произвольно, а вызов input() для каждой строки медленный. Надёжнее прочитать весь ввод разом и разрезать его:

import sys

data = sys.stdin.read().split()
n, m = int(data[0]), int(data[1])
values = list(map(int, data[2:2 + n * m]))
matrix = [values[i * m:(i + 1) * m] for i in range(n)]
print(matrix)

Для ввода 2 3, 1 2, 3 4 5, 6 (на разных строках) программа всё равно выведет [[1, 2, 3], [4, 5, 6]]: split() без аргументов не различает пробелы и переводы строк.

Поле из символов

Лабиринты и игровые поля часто подаются строками символов без пробелов. Функция list() разбивает строку на отдельные символы:

n = int(input())                        # 3
grid = [list(input()) for _ in range(n)]  # #.. / .#. / ..#
print(grid)        # → [['#', '.', '.'], ['.', '#', '.'], ['.', '.', '#']]
print(grid[1][2])  # → .

Если поле только читается и не меняется, можно хранить строки как есть: grid[1][2] работает и для строки str.

Проверка ввода

Если пользователь ввёл в строке меньше чисел, матрица станет «рваной», а ошибка всплывёт позже. Проверьте длину сразу:

n, m = map(int, input().split())
matrix = []
for i in range(n):
    row = list(map(int, input().split()))
    if len(row) != m:
        raise ValueError(f"строка {i + 1}: нужно чисел {m}, введено {len(row)}")
    matrix.append(row)

Числа через запятую («1,2,3» или «1, 2, 3») разбирают так: input().replace(",", " ").split().

Как вывести двумерный массив

print(matrix) печатает всю матрицу одной строкой со скобками. Чтобы вывести её таблицей, перебирают строки циклом for:

matrix = [[1, 2, 3], [40, 50, 60], [700, 800, 900]]

for row in matrix:
    print(*row)                        # элементы через пробел

for row in matrix:
    print(" ".join(map(str, row)))     # то же через join

for row in matrix:
    print(*row, sep="\t")              # через табуляцию
1 2 3
40 50 60
700 800 900

print(*row) распаковывает строку в отдельные аргументы — это самый короткий вариант для задач, где числа нужно разделить одним пробелом. join работает только со строками, поэтому числа сначала превращают в str.

Для ровных столбцов задайте ширину поля в f-строке. Ширину можно вычислить по самому длинному числу:

matrix = [[1, 2, 3], [40, 50, 60], [700, 800, 900]]
width = max(len(str(x)) for row in matrix for x in row)
for row in matrix:
    print(" ".join(f"{x:>{width}}" for x in row))
  1   2   3
 40  50  60
700 800 900

Для отладки больших вложенных структур удобен модуль pprint: pprint(matrix, width=40) переносит каждую строку матрицы на новую строку экрана.

Обход двумерного массива

По строкам

Два вложенных цикла: внешний перебирает строки, внутренний — элементы строки. Когда нужны индексы, используйте enumerate() вместо range(len(...)):

matrix = [[1, 2, 3], [4, 5, 6]]
for i, row in enumerate(matrix):
    for j, value in enumerate(row):
        print(f"[{i}][{j}] = {value}")
[0][0] = 1
[0][1] = 2
[0][2] = 3
[1][0] = 4
[1][1] = 5
[1][2] = 6

Если нужно менять элементы, присваивайте через индексы: matrix[i][j] = .... Присваивание переменной цикла value = 0 матрицу не меняет.

По столбцам

Столбец не хранится отдельно, его собирают из строк. Внешний цикл идёт по столбцам, внутренний — по строкам:

matrix = [[1, 2, 3], [4, 5, 6]]
rows, cols = len(matrix), len(matrix[0])
for j in range(cols):
    column = [matrix[i][j] for i in range(rows)]
    print(j, column)
0 [1, 4]
1 [2, 5]
2 [3, 6]

Один столбец получают короче: [row[1] for row in matrix] вернёт [2, 5]. Перебрать все столбцы сразу помогает zip(*matrix) — о нём в разделе про транспонирование.

По диагоналям

В квадратной матрице n × n элементы главной диагонали имеют индексы i == j, побочной — j == n - 1 - i. Выше главной диагонали лежат элементы с j > i, ниже — с j < i:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
n = len(matrix)
main = [matrix[i][i] for i in range(n)]
anti = [matrix[i][n - 1 - i] for i in range(n)]
print(main, anti)    # → [1, 5, 9] [3, 5, 7]

above = [matrix[i][j] for i in range(n) for j in range(n) if j > i]
below = [matrix[i][j] for i in range(n) for j in range(n) if j < i]
print(above, below)  # → [2, 3, 6] [4, 7, 8]

Для диагонали достаточно одного цикла: for i in range(n): matrix[i][i] = 0. Двойной цикл с проверкой if i == j даёт тот же результат, но перебирает лишние n² − n элементов.

Соседи клетки

В задачах на поле (лабиринт, «Сапёр», игра «Жизнь») нужно перебрать соседей клетки, не выходя за границы. Смещения записывают списком пар:

grid = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

def neighbors(grid, i, j):
    rows, cols = len(grid), len(grid[0])
    for di, dj in ((-1, 0), (1, 0), (0, -1), (0, 1)):
        ni, nj = i + di, j + dj
        if 0 <= ni < rows and 0 <= nj < cols:
            yield grid[ni][nj]

print(list(neighbors(grid, 0, 0)))  # → [4, 2]
print(list(neighbors(grid, 1, 1)))  # → [2, 8, 4, 6]

Проверка 0 <= ni обязательна: индекс -1 не вызовет ошибку, а молча вернёт элемент с другого края матрицы.

Транспонирование: zip(*matrix)

Транспонирование меняет строки и столбцы местами. Встроенная функция zip с распаковкой *matrix получает строки как отдельные аргументы и собирает из них столбцы:

matrix = [[1, 2, 3], [4, 5, 6]]
print(list(zip(*matrix)))  # → [(1, 4), (2, 5), (3, 6)]

transposed = [list(col) for col in zip(*matrix)]
print(transposed)          # → [[1, 4], [2, 5], [3, 6]]

zip возвращает кортежи. Если результат нужно менять, превратите их в списки, как во второй строке, или через list(map(list, zip(*matrix))).

Две особенности при работе с «рваными» строками:

  • zip останавливается на самой короткой строке и молча теряет лишние элементы: zip(*[[1, 2, 3], [4, 5]]) даст только два столбца.
  • С Python 3.10 параметр strict=True превращает это в ошибку: ValueError: zip() argument 2 is shorter than argument 1.

Квадратную матрицу можно транспонировать на месте, обменивая элементы над диагональю с элементами под ней:

m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
n = len(m)
for i in range(n):
    for j in range(i + 1, n):
        m[i][j], m[j][i] = m[j][i], m[i][j]
print(m)  # → [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Поворот и отражение матрицы

Повороты на 90° собираются из транспонирования и разворота срезом [::-1]:

m = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
cw = [list(row) for row in zip(*m[::-1])]   # по часовой стрелке
ccw = [list(row) for row in zip(*m)][::-1]  # против часовой
flip_v = m[::-1]                            # строки в обратном порядке
flip_h = [row[::-1] for row in m]           # каждая строка задом наперёд

print(cw)      # → [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
print(ccw)     # → [[3, 6, 9], [2, 5, 8], [1, 4, 7]]
print(flip_v)  # → [[7, 8, 9], [4, 5, 6], [1, 2, 3]]
print(flip_h)  # → [[3, 2, 1], [6, 5, 4], [9, 8, 7]]

m[::-1] создаёт новый внешний список, но строки в нём те же объекты, что в m. Если результат будут менять, скопируйте строки: [row[:] for row in m[::-1]].

Поиск элемента

Оператор in сравнивает искомое значение с целыми строками матрицы, поэтому 7 in matrix вернёт False, даже если число 7 там есть. Проверяйте каждую строку через any:

matrix = [[3, 8, 1], [9, 2, 7], [4, 6, 5]]
print(7 in matrix)                      # → False
print(any(7 in row for row in matrix))  # → True

Чтобы узнать позицию, верните пару индексов из функции — return прерывает оба цикла сразу:

def find(matrix, value):
    for i, row in enumerate(matrix):
        for j, x in enumerate(row):
            if x == value:
                return i, j
    return None

print(find(matrix, 7))   # → (1, 2)
print(find(matrix, 10))  # → None

evens = [(i, j) for i, row in enumerate(matrix)
         for j, x in enumerate(row) if x % 2 == 0]
print(evens)  # → [(0, 1), (1, 1), (2, 0), (2, 1)]

Максимум и минимум всей матрицы, а также позиция максимума:

matrix = [[3, 8, 1], [9, 2, 7], [4, 6, 5]]
print(max(map(max, matrix)), min(map(min, matrix)))  # → 9 1

value, i, j = max((x, i, j) for i, row in enumerate(matrix)
                  for j, x in enumerate(row))
print(value, i, j)  # → 9 1 0

max(matrix) без map сравнивает строки как списки и вернёт строку [9, 2, 7] целиком.

Сумма элементов: по строкам, столбцам и диагоналям

matrix = [[3, 8, 1], [9, 2, 7], [4, 6, 5]]
n = len(matrix)

print(sum(map(sum, matrix)))                 # → 45 (вся матрица)
print([sum(row) for row in matrix])          # → [12, 18, 15] (строки)
print([sum(col) for col in zip(*matrix)])    # → [16, 16, 13] (столбцы)
print(sum(matrix[i][i] for i in range(n)))   # → 10 (главная диагональ)
print(sum(matrix[i][n - 1 - i] for i in range(n)))  # → 7 (побочная)

count = sum(map(len, matrix))
print(sum(map(sum, matrix)) / count)         # → 5.0 (среднее)
print(sum(1 for row in matrix for x in row if x > 5))  # → 4 (больше пяти)

sum(matrix) без map вызовет TypeError: функция пытается сложить число 0 со списком.

Сортировка двумерного массива

Что именно сортировать, зависит от задачи:

matrix = [[3, 8, 1], [9, 2, 7], [4, 6, 5]]
for row in matrix:   # каждую строку отдельно, на месте
    row.sort()
print(matrix)        # → [[1, 3, 8], [2, 7, 9], [4, 5, 6]]

students = [["Оля", 17, 4.5], ["Иван", 16, 4.9], ["Анна", 17, 4.1]]
print(sorted(students, key=lambda r: r[2], reverse=True))
# → [['Иван', 16, 4.9], ['Оля', 17, 4.5], ['Анна', 17, 4.1]]
print(sorted(students, key=lambda r: (r[1], r[0])))
# → [['Иван', 16, 4.9], ['Анна', 17, 4.1], ['Оля', 17, 4.5]]

nums = [[3, 3], [1, 9], [2, 2]]
print(sorted(nums, key=sum))  # → [[2, 2], [3, 3], [1, 9]]
print(sorted(nums))           # → [[1, 9], [2, 2], [3, 3]]
  • Строки целиком сортируются как обычные элементы списка. Без key Python сравнивает их поэлементно: сначала первый элемент, при равенстве — второй.
  • key=lambda r: r[2] сортирует строки по третьему столбцу, кортеж в key задаёт несколько уровней сортировки. Вместо lambda можно взять operator.itemgetter(1, 0).

Отсортировать все значения матрицы и разложить их обратно по строкам:

matrix = [[3, 8, 1], [9, 2, 7], [4, 6, 5]]
m = len(matrix[0])
flat = sorted(x for row in matrix for x in row)
result = [flat[i:i + m] for i in range(0, len(flat), m)]
print(result)  # → [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Каждый столбец сортируют через двойное транспонирование: [list(c) for c in zip(*[sorted(col) for col in zip(*matrix)])].

Добавление и удаление строк и столбцов

matrix = [[1, 2, 3], [4, 5, 6]]
matrix.append([7, 8, 9])     # строка в конец
matrix.insert(0, [0, 0, 0])  # строка в начало
for row in matrix:           # столбец в конец: сумма строки
    row.append(sum(row))
print(matrix)  # → [[0, 0, 0, 0], [1, 2, 3, 6], [4, 5, 6, 15], [7, 8, 9, 24]]

del matrix[0]                # удалить строку 0
for row in matrix:           # удалить столбец 1
    del row[1]
print(matrix)  # → [[1, 3, 6], [4, 6, 15], [7, 9, 24]]

Операции со строками — это методы внешнего списка. Столбец всегда меняют циклом по всем строкам, иначе матрица перестанет быть прямоугольной.

Копирование: copy, срезы и deepcopy

Присваивание b = a не копирует матрицу, а a.copy() и a[:] копируют только внешний список — строки остаются общими:

import copy

a = [[1, 2], [3, 4]]
alias = a                      # та же матрица
shallow = a.copy()             # новый внешний список, строки общие
rows = [row[:] for row in a]   # копия каждой строки
deep = copy.deepcopy(a)        # полная копия любой вложенности

a[0][0] = 99
print(alias[0][0], shallow[0][0], rows[0][0], deep[0][0])  # → 99 99 1 1
СпособНовый внешний списокНовые строкиКогда использовать
b = aнетнетнужна вторая ссылка на ту же матрицу
a.copy(), a[:]данеттолько переставить или удалить строки
[row[:] for row in a]дадаматрица чисел или строк, нужна независимая копия
copy.deepcopy(a)дадав ячейках списки, словари и другие изменяемые объекты

Для матрицы чисел копия строк срезами работает заметно быстрее: в нашем замере на матрице 100 × 100 — примерно в 50 раз быстрее deepcopy. Две матрицы сравнивают оператором ==: он проверяет значения поэлементно, а is — один ли это объект.

NumPy-массив или список списков

Список списков подходит для учебных задач, полей из символов, таблиц со смешанными типами и матриц, которые меняют размер. Для вычислений над большими числовыми матрицами лучше библиотека NumPy: её массив ndarray хранит числа компактно и выполняет операции сразу над всей матрицей, без циклов Python.

import numpy as np

a = np.array([[3, 8, 1], [9, 2, 7]])
print(a.shape)       # → (2, 3)
print(a[1, 2])       # → 7
print(a[:, 1])       # → [8 2] (столбец без цикла)
print(a.T)           # транспонирование
print(a.sum(axis=0), a.sum(axis=1))  # → [12 10  8] [12 18]
print(a * 10)        # умножение каждого элемента
print(a.tolist())    # → [[3, 8, 1], [9, 2, 7]] (обратно в список списков)

np.zeros((n, m), dtype=int) создаёт матрицу нулей без ловушки со ссылками, а a @ b перемножает матрицы. В нашем замере сумма по столбцам матрицы 500 × 500 в NumPy выполнялась примерно в 50 раз быстрее, чем [sum(c) for c in zip(*lst)].

КритерийСписок списковnumpy.ndarray
Установкавстроен в Pythonpip install numpy
Типы элементовлюбые, вперемешкуодин тип (dtype) на весь массив
Размерстроки разной длины, appendфиксированная прямоугольная форма
Индексацияm[i][j], столбец — цикломa[i, j], столбец — a[:, j]
Математикациклы и генераторывекторные операции, @, axis
Где уместенучебные задачи, поля, таблицычисловые расчёты, данные, изображения

Создание массивов, dtype, reshape и broadcasting разобраны в статье про NumPy.

Частые ошибки

IndexError: list index out of range

Индекс вышел за границы: matrix[2][0] при двух строках. Чаще всего перепутаны n и m — например, внешний цикл идёт до числа столбцов. Проверьте, что i перебирает range(len(matrix)), а j — range(len(matrix[i])).

Числа остались строками

Без int или map(int, ...) матрица хранит строки '10', '9'. Сортировка тогда идёт по алфавиту ('10' < '9'), max выбирает '9', а sum падает с TypeError: unsupported operand type(s) for +: 'int' and 'str'.

Все строки меняются одновременно

Матрица создана через [[0] * m] * n или в неё несколько раз добавлен один и тот же список. Создавайте каждую строку заново — генератором или append([...]) внутри цикла.

Частые вопросы

Как узнать размер двумерного массива?

Число строк — len(matrix), число столбцов — len(matrix[0]). Для «рваного» массива длины строк разные: [len(row) for row in matrix]. Проверить, что матрица прямоугольная, можно так: all(len(row) == len(matrix[0]) for row in matrix).

Как превратить двумерный массив в одномерный?

Генератором с двумя for: [x for row in matrix for x in row]. Для больших матриц удобен itertools.chain.from_iterable(matrix). Вариант sum(matrix, []) тоже работает, но на больших данных медленный: каждое сложение создаёт новый список.

Как создать трёхмерный массив?

Тем же вложенным генератором, ещё одним уровнем глубже: cube = [[[0] * k for _ in range(m)] for _ in range(n)], обращение — cube[i][j][t]. Правило то же: умножать через * можно только самый внутренний список с неизменяемыми значениями.

Как сохранить матрицу в файл и прочитать обратно?

Модулем csv из стандартной библиотеки:

import csv

matrix = [[1, 2, 3], [4, 5, 6]]
with open("matrix.csv", "w", newline="", encoding="utf-8") as f:
    csv.writer(f).writerows(matrix)

with open("matrix.csv", encoding="utf-8") as f:
    loaded = [[int(x) for x in row] for row in csv.reader(f)]
print(loaded)  # → [[1, 2, 3], [4, 5, 6]]

csv.reader возвращает строки, поэтому числа нужно снова превратить в int.

Как перемножить две матрицы без NumPy?

Каждый элемент результата — сумма произведений строки первой матрицы на столбец второй:

def matmul(a, b):
    return [[sum(x * y for x, y in zip(row, col)) for col in zip(*b)] for row in a]

print(matmul([[1, 2], [3, 4]], [[5, 6], [7, 8]]))  # → [[19, 22], [43, 50]]

Число столбцов первой матрицы должно совпадать с числом строк второй. Для реальных расчётов используйте a @ b в NumPy.

Чем двумерный массив отличается от списка кортежей или словаря?

Список списков удобен, когда к ячейкам обращаются по номеру строки и столбца и значения меняются. Список кортежей подходит для неизменяемых записей. Если матрица почти пустая, например поле 10 000 × 10 000 с несколькими занятыми клетками, экономнее словарь с ключами-парами: cells[(i, j)] = value.

Итог

  • Двумерный массив в Python — список списков, элемент читается как matrix[i][j].
  • Создавайте матрицу генератором [[0] * m for _ in range(n)]; запись [[0] * m] * n делает все строки одним объектом.
  • Ввод: list(map(int, input().split())) для каждой строки, для больших данных — sys.stdin.read().split() и нарезка срезами.
  • Вывод таблицей — print(*row) в цикле, ровные столбцы — f-строка с шириной поля.
  • Столбцы и транспонирование — zip(*matrix), повороты — сочетание zip и [::-1].
  • Независимая копия — [row[:] for row in matrix] или copy.deepcopy().
  • Для больших числовых матриц переходите на NumPy.

Остальной синтаксис языка собран в шпаргалке по синтаксису Python.

  • #Python
  • #Списки
  • #Массивы
  • #Матрицы
  • #Синтаксис
↑ ↓ выборEnter открытьEsc закрыть