Давайте начнем с самого начала и исследуем его немного глубже:
Итак, предположим, у вас есть два списка:
list_1=['01','98']
list_2=[['01','98']]
И мы должны скопировать оба списка, теперь начиная с первого списка:
Итак, сначала давайте попробуем по общему методу копирования:
copy=list_1
Теперь, если вы думаете, что скопировал список_1, то вы можете ошибаться, давайте проверим это:
The id() function shows us that both variables point to the same list object, i.e. they share this object.
print(id(copy))
print(id(list_1))
выход:
4329485320
4329485320
Удивлен? Хорошо, давайте исследуем это:
Итак, как мы знаем, python ничего не хранит в переменной, переменные просто ссылаются на объект, а объект хранит значение. Здесь объект list
, но мы создали две ссылки на этот же объект под двумя разными именами переменных. Таким образом, обе переменные указывают на один и тот же объект:
поэтому, когда вы делаете copy=list_1
, что на самом деле делает:
Здесь на изображении list_1 и copy два имени переменных, но объект одинаков для обеих переменных, что составляет list
Таким образом, если вы попытаетесь изменить скопированный список, то он также изменит исходный список, поскольку список там только один, вы будете изменять этот список независимо от того, делаете ли вы это из скопированного списка или из исходного списка:
copy[0]="modify"
print(copy)
print(list_1)
выход:
['modify', '98']
['modify', '98']
Таким образом, он изменил исходный список:
Каково решение тогда?
Решение:
Теперь перейдем ко второму питоническому методу копирования списка:
copy_1=list_1[:]
Теперь этот метод исправляет то, с чем мы столкнулись в первом выпуске, давайте проверим это:
print(id(copy_1))
print(id(list_1))
4338792136
4338791432
Итак, мы видим, что оба списка имеют разные идентификаторы, и это означает, что обе переменные указывают на разные объекты, поэтому на самом деле происходит следующее:
Теперь давайте попробуем изменить список и посмотрим, сталкиваемся ли мы с предыдущей проблемой:
copy_1[0]="modify"
print(list_1)
print(copy_1)
Выход:
['01', '98']
['modify', '98']
Итак, как вы можете видеть, он не изменяет исходный список, он только изменяет скопированный список, так что мы в порядке.
Так что теперь я думаю, что мы закончили? подождите, мы тоже должны скопировать второй вложенный список, так что давайте попробуем питонски:
copy_2=list_2[:]
Итак, list_2 должен ссылаться на другой объект, который является копией list_2, давайте проверим:
print(id((list_2)),id(copy_2))
получаем результат:
4330403592 4330403528
Теперь мы можем предположить, что оба списка указывают на разные объекты, поэтому теперь давайте попробуем изменить его и посмотрим, что он дает то, что нам нужно:
Итак, когда мы попробуем:
copy_2[0][1]="modify"
print(list_2,copy_2)
это дает нам вывод:
[['01', 'modify']] [['01', 'modify']]
Теперь, это немного сбивает с толку, мы использовали питонский способ, и все же, мы сталкиваемся с той же проблемой.
давайте разберемся:
Итак, когда мы делаем:
copy_2=list_2[:]
мы на самом деле копируем только внешний список, а не вложенный список, поэтому вложенный список является одним и тем же объектом для обоих списков, давайте проверим:
print(id(copy_2[0]))
print(id(list_2[0]))
выход:
4329485832
4329485832
Так что на самом деле, когда мы делаем copy_2=list_2[:]
, вот что происходит:
Создает копию списка, но только копию внешнего списка, а не копию вложенного списка, вложенный список одинаков для обеих переменных, поэтому, если вы попытаетесь изменить вложенный список, он также изменит исходный список, потому что объект вложенного списка одинаковы для обоих вложенных списков.
Так в чем же решение?
Решение deep copy
from copy import deepcopy
deep=deepcopy(list_2)
Итак, давайте проверим это:
print(id((list_2)),id(deep))
выход:
4322146056 4322148040
оба идентификатора различны, теперь давайте проверим идентификатор вложенного списка:
print(id(deep[0]))
print(id(list_2[0]))
выход:
4322145992
4322145800
Как видите, оба идентификатора различны, поэтому мы можем предположить, что оба вложенных списка теперь указывают на разные объекты.
Итак, когда вы делаете deep=deepcopy(list_2)
, что на самом деле происходит:
Таким образом, оба вложенных списка указывают на разные объекты, и теперь у них есть отдельная копия вложенного списка.
Теперь давайте попробуем изменить вложенный список и посмотрим, решил ли он предыдущую проблему или нет:
так что если мы сделаем:
deep[0][1]="modify"
print(list_2,deep)
выход:
[['01', '98']] [['01', 'modify']]
Итак, как вы можете видеть, он не изменил исходный вложенный список, он только изменил скопированный список.
Если вам нравится мой подробный ответ, дайте мне знать, проголосовав за него,
если у вас есть какие-либо сомнения, поняли этот ответ, прокомментируйте:)