Назначение нарезки, мелкое/глубокое копирование

Итак, я так понимаю:

a_list = [1,2,3]
b_list = [5,6,7]
a_list.append(b_list) 

a_list в настоящее время [1,2,3, [5,6,7]]

c_list = a_list[:]
b_list[0] = 1000
print(a_list, c_list)

список [1,2,3,[1000,6,7]]

c_list это [1,2,3,[1000,6,7]]

a_list и c_list оба изменены, потому что, когда b_list было добавлено к a_list, b_list было ссылкой на [5,6,7], и любое изменение в b_list показывает изменение в a_list и c_list. Это хорошо.

Проблема в том, когда у вас есть:

a_list = [1, 2, [1,5,0]]
b_list = a_list[:]
a_list[2][1] = 90000
print(a_list, b_list)

a_list — это [1, 2, [1, 90000, 0]], а b_list — это [1, 2, [1, 90000, 0]].

Почему b_list изменилось? b_list — это неглубокая копия a_list, которая, если бы у нее были ссылки, копировала бы ссылки, а не фактические объекты. Однако у a_list нет ссылок для копирования; это точное значение, список чисел, и b_list не должно меняться, если какое-то значение в a_list изменилось, поскольку они совершенно разные, b_list не указывает на a_list через присваивание.


person Art    schedule 06.11.2017    source источник
comment
Вложенный список по-прежнему является ссылкой. Переменные — это именованные ссылки, индексы в списке — нумерованные ссылки.   -  person Martijn Pieters    schedule 06.11.2017
comment
Неглубокая копия — это новый список, элементы которого совпадают с элементами исходного списка (не копии этих элементов). Если вы хотите рекурсивно скопировать элементы, используйте copy.deepcopy.   -  person Tom Karzes    schedule 06.11.2017


Ответы (1)


Все в Python является ссылкой. Индексы списка — это просто ссылки, как и имена (переменные).

Итак, a_list[2] — это ссылка на объект списка, точно так же, как a_list[0] — это ссылка на целочисленный объект. Вы создали поверхностную копию a_list, что означает, что все 3 ссылки были скопированы в новый объект списка.

Следовательно, b_list[2] ссылается на тот же объект, что и a_list[2], другой объект списка. изменение этого объекта списка с помощью a_list[2] или b_list[2] сделает изменение видимым через любой из них.

Если вам также нужно скопировать объекты, на которые есть ссылки, создайте глубокую копию. Вы можете использовать copy.deepcopy() для рекурсивного копирования всего или использовать понимание списка для создания поверхностных копий только непосредственно вложенных списков.

person Martijn Pieters    schedule 06.11.2017