TGViewer
Physics.Math.Code Physics.Math.Code @physics_lib · 147K subscribers
Post #15154 23.8K
🖥 Списочные ловушки Python: умножение и вложенность

В этой заметке разберем классический подвох, на котором спотыкаются даже опытные разработчики. Рассмотрим код:
a = [[]] * 3
a[0].append(1)
print(a)

Что будет на выводе в консоли? A) [[1], [], []] B) [[1]] C) [[1], [1], [1]] D) Ошибка
Правильный ответ: C) [[1], [1], [1]]

А если мы увеличим вложенность списков?
a = [[[]]] * 3
a[0].append(1)
print(a)

Что выведет? Подумайте, прежде чем открывать ответ.
Правильный ответ: [[[], 1], [[], 1], [[], 1]]

📚 Ошиблись? Тогда давайте разбираться. Теория того как работает умножение списков

▪️ 1. Главное правило: Операция [x] * n работает так:
➖ Создается объект x
➖ Создается список из n элементов
➖ Каждый элемент — это ссылка на один и тот же объект x
Это называется поверхностным (shallow) копированием.
a = [[]] * 3 Реально в памяти: a = [ссылка_на_список, ссылка_на_список, ссылка_на_список]

▪️ 2. Почему с числами всё проще, а со списками — нет?
b = [1] * 3
b[0] = 5
print(b) # [5, 1, 1] всё работает

Числа — неизменяемые. Когда мы пишем b[0] = 5, мы не меняем объект 1, а переназначаем ссылку на новый объект 5. Остальные элементы продолжают ссылаться на 1.
Со списками иначе:
a = [[]] * 3
a[0].append(1) # МЕНЯЕМ сам объект, а не переназначаем ссылку

Метод.append() изменяет существующий список, не создавая новый. Поэтому изменения видны через все ссылки.
a = [[]] * 3
a[0].append(1)
print(a) # [[1], [1], [1]]

a = [[[]]] * 3
a[0].append(1)
print(a) # [[[], 1], [[], 1], [[], 1]]

a = [[[]]] * 3
a[0][0].append(1) # Два индекса!
print(a) # [[[1]], [[1]], [[1]]]

a = [[[]]] * 3
a[0] = 100 # ПЕРЕНАЗНАЧАЕМ ссылку
print(a) # [100, [[ ]], [[ ]]]

a = [[], [], []] # уже три разных списка
a[0].append(1) # меняем только первый
print(a) # [[1], [], []]

▪️Как создать независимые списки?
a = [[] for _ in range(3)]
a[0].append(1)
print(a) # [[1], [], []]

a = [[[]] for _ in range(3)]
a[0].append(1)
print(a) # [[[], 1], [[]], [[]]]

Глубокое копирование:
import copy
a = [copy.deepcopy([[]]) for _ in range(3)]

Классика циклом:
a = []
for _ in range(3):
a.append([])

1. Умножение списков ≠ создание копий объектов — это создание копий ссылок.
2. Для изменяемых объектов (списки, словари, множества) проблема особенно заметна.
3. Для неизменяемых (числа, строки, кортежи) проблема скрыта, но механизм тот же.
4. Всегда используй генератор списков, если нужны независимые вложенные структуры.
5. a[0].append() — изменение объекта; a[0] = ... — переназначение ссылки

▪️Для проверки понимания задачи. Что выведет этот код?
a = [[0]] * 3
a[1][0] = 5
print(a)

#программирование #python #задачи #алгоритмы #computer_science #собеседования

💡 Physics.Math.Code // @physics_lib
  • ❤ 42
  • 👍 21
  • 🔥 17
  • 🤯 12
  • 🤔 4
  • 👻 4
  • 🗿 4
  • ⚡ 1
  • 🤩 1
  • 👨‍💻 1
  • 👾 1
More from @physics_lib
  1. Sep 24, 2026🥺 Plasma Vortex in a Magnetic Field ⚡️ Видео демонстрирует классический и очень наглядный…
  2. Sep 23, 2026🌪 Однополостный гиперболоид — кривая поверхность держит небоскрёбы Представьте поверхност…
  3. Sep 22, 2026🧊 Интересный опыт: Лёд под проволокой Что будет происходить с ледяным бруском, если на не…
  4. Sep 22, 2026🔥 Сварка трением, иначе фрикционная сварка. Несколько патентов на эту тему было ещё в 20е…
  5. Sep 22, 2026📚 Физика (Американский курс физики для средней школы) [1973-1974] Комитет содействия изуч…
  6. Sep 22, 2026📚 Физика (Американский курс физики для средней школы) [1973-1974] Комитет содействия изуч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →