Изменение элементов списка в мелкой копии
У меня есть один вопрос по списку мелкой копии.
В обоих примерах я изменил один элемент списка, но в примере 1 список b
изменили, а в примере 2 список d
не изменился. Я в замешательстве, так как в обоих примерах я изменил элемент списка.
Какая разница?
Пример 1:
a=[1,2,[3,5],4]
b=list(a)
a[1]=0
print(a) # [1, 0, [3, 5], 4]
print(b) # [1, 2, [3, 5], 4]
Пример 2:
c=[1,2,[3,5],4]
d=list(c)
c[2][0]=0
print(c) # [1, 2, [0, 5], 4]
print(d) # [1, 2, [0, 5], 4]
2 ответа
Мелкая копия означает, что вы получаете новый список, но элементы одинаковы. Таким образом, оба списка имеют одинаковый первый элемент, второй элемент и т. Д.
Если вы добавляете, удаляете или заменяете значение из мелкого скопированного списка, это изменение не отражается в оригинале (и наоборот), поскольку мелкая копия создала новый список. Однако, если вы измените элемент в любом из них, это изменение будет видно в обоих, поскольку оба списка ссылаются на один и тот же элемент. Таким образом, внутренний список фактически распределяется между новым списком и старым списком, и если вы его измените, это изменение будет видно в обоих.
Обратите внимание, что вы на самом деле не изменили элемент ни в одном из примеров, вы заменяете элемент списка в первом примере, а во втором - заменяете элемент элемента вашего списка.
В настоящее время я часто использую Graphviz, поэтому позвольте мне добавить несколько изображений, чтобы проиллюстрировать это:
Мелкая копия означает, что вы получаете новый список, но объекты, хранящиеся в списке, совпадают:
Если вы замените элемент любого из них, соответствующий элемент будет просто ссылаться на новый элемент (ваш первый пример). Посмотрите, как один список ссылается на два, а другой на ноль:
В то время как изменение ссылочного элемента изменит этот элемент, и каждый объект, который ссылается на этот элемент, увидит изменение:
[
1. = копирует ссылку на объект, следовательно, любые изменения в одном списке отражаются в другом
-
b=list(a) or b=a.copy()
-> проделайте ту же работу. То есть он копирует ссылку только на отдельные объекты, например, b[0]=a[0] и b= a 2 и так далее. С int, string и т. Д. Это как если x = 10 и y = x, и изменение значения "x" или "y" не повлияет на другое. Это то, что происходит с оставшимися элементами a и b, когда вы делаете неглубокую копию.
Как и в вашем вопросе при выполнении
b=list(a) and a[1]=0
использование неглубокой копии ведет себя так, как описано выше, и, следовательно, изменения не отражаются в обоих списках. Но вложенный список действует как назначение списка, например
a=[1,2,3]
и
b=a
а установка a 2 = 3 также изменит b 2 на 3, т.е. изменения a или b влияют на оба (как в случае 1 выше). Вот почему в случае списка с в списке любые изменения отражаются в обоих списках. Как в вашем примере, делая
d=list(c)
(здесь при копировании
d[2]=c[2]
это похоже на назначение списка, т.е. ссылка копируется, и в случае изменения назначения списка отражаются в обоих, поэтому изменения в d 2 или c 2 отражаются в обоих списках)
c[2][0] = 0
также изменит значение d[2][0] на ноль.
Попробуйте использовать код на http://www.pythontutor.com/visualize.html#mode=edit, чтобы лучше понять
a=[1,2,"hello",[3,4],5]
b=a
c=a.copy()
a[0]=2
a[3][0]=6
В обоих примерах вы создаете поверхностную копию списка. Мелкие копии по существу копируют псевдонимы для всех элементов первого списка во второй список.
Итак, вы скопировали ссылку на [int, int, list, int]
, int
элементы неизменны, но list
элемент изменчив. Таким образом, третьи элементы указывают на один и тот же объект в памяти Python. Изменение этого объекта изменяет все ссылки на него.