Изменение элементов списка в мелкой копии

У меня есть один вопрос по списку мелкой копии.

В обоих примерах я изменил один элемент списка, но в примере 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. = копирует ссылку на объект, следовательно, любые изменения в одном списке отражаются в другом

  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. Изменение этого объекта изменяет все ссылки на него.

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