Внутри вложенных циклов добавление списка в новый список дает неожиданный результат

Я попытался написать свою проблему с ошибкой воспроизводимым образом, чтобы платформа могла быть видна и управляема. Я не вижу своего логического пробела, почему возникает эта ошибка. У меня есть внутренний цикл, который приносит новые элементы при очистке и добавляет их в список с именем list_inner. Затем в список внешнего цикла с именем list_outer добавляется этот новый список. Но окончательный результат дает правильное количество членов, но элементы списка list_outer такие же, последний элемент списка списка list_inner. Как это может произойти? Если это будет один элементный список, то я пойму.

import random
list_inner=[]
list_outer=[]
for i in range(5):
    for r in range(random.randint(1,10)):
        list_inner.append(r)
        print(r)
    list_outer.append(list_inner)
    print(list_outer)
print(list_outer)

Я делюсь двумя результатами, поскольку даю представление о том, что есть на самом деле, и о том, чего я ожидал. Я получил этот результат:

0
1
2
3
[[0, 1, 2, 3]]
0
1
2
3
4
[[0, 1, 2, 3, 0, 1, 2, 3, 4], [0, 1, 2, 3, 0, 1, 2, 3, 4]]

Но я ожидал такого результата:

[[0,1,2,3],[0,1,2,3,4]]
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Здесь действительно две проблемы:

  • Вы не очищаете list_inner в конце каждого внешнего цикла, поэтому он сохраняет все элементы из всех итераций до сих пор.
  • Вы добавляете list_inner непосредственно к list_outer вместо добавления копии list_inner. Это означает, что когда list_inner изменяется, ссылка на него, которая уже была помещена внутри list_outer, также изменяется. Таким образом, вы получите то же самое, что и в list_outer.

Все, что вам нужно сделать, это изменить свой код на копирование list_inner перед его добавлением, а также очистить list_inner в конце каждого внешнего цикла:

import random

list_inner = []
list_outer = []
for i in range(5):
    for r in range(random.randint(1,10)):
        list_inner.append(r)
    list_outer.append(list_inner.copy())
    list_inner.clear()

print(list_outer)

Пример вывода:

[[0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2], [0, 1, 2, 3, 4, 5, 6], [0, 1], [0, 1, 2, 3]]

Что трудно переварить, почему мы должны использовать в вашем ответе list_inner.copy в моем ответе я сказал это так, list_outer.append(list(list_inner)). Вроде пробовал и получилось. Но зачем нужно копировать или составлять список добавленных данных, чтобы добавить его в виде списка? Был бы признателен, если бы ответил на это

xlmaster 15.04.2023 17:57

@xlmaster list_inner.copy() и list(list_inner) делают одно и то же — делают копию списка — хотя использование list_inner.copy() лучше, так как ясно, что на самом деле делается. Причина, по которой нам нужно скопировать список, заключается в том, что если мы этого не сделаем, мы добавим ссылку на list_inner, которая также будет изменяться всякий раз, когда изменяется list_inner. Поэтому, когда мы очистим список и начнем добавлять новые значения, ссылка, которую мы вставили в list_outer, также изменится таким же образом. Вот почему вы получаете несколько копий одного и того же объекта в list_outer. Копирование списка предотвращает это.

Lecdi 15.04.2023 18:23

Я решил проблему, добавив список методов в inner_loop перед методом добавления и поместив список во внешний цикл. Вот код

import random

list_outer=[]
for i in range(5):
    list_inner = []
    for r in range(random.randint(1,5)):
        list_inner.append(r)
        print(r,list_inner)
    list_outer.append(list(list_inner))
    print('list outer',list_outer)
print(list_outer)

Другие вопросы по теме