Как мне скопировать только значения, а не ссылки из списка Python?

В частности, я хочу создать резервную копию списка, затем внести некоторые изменения в этот список, добавить все изменения в третий список, но затем сбросить первый список с резервной копией, прежде чем делать дальнейшие изменения и т. Д., Пока я не закончу вносить изменения и хотите скопировать весь контент из третьего списка в первый. К сожалению, кажется, что всякий раз, когда я делаю изменения в первом списке в другой функции, резервная копия также изменяется. С помощью original = backup не работал слишком хорошо; и не использовал

def setEqual(restore, backup):
    restore = []
    for number in backup:
        restore.append(number)

решить мою проблему; хотя я успешно восстановил список из резервной копии, резервная копия, тем не менее, менялась всякий раз, когда я изменял исходный список.

Как бы я решил эту проблему?

2 ответа

Решение

Первое, что нужно понять, это почему setEqual метод не может работать: вам нужно знать, как работают идентификаторы. (Чтение этой ссылки должно быть очень полезным.) Для краткого изложения с, вероятно, слишком большой терминологией: в вашей функции параметр restore привязан к объекту, и вы просто повторно связываете этот идентификатор с = оператор. Вот несколько примеров привязки идентификатора restore к вещам.

# Bind the identifier `restore` to the number object 1.
restore = 1
# Bind the identifier `restore` to the string object 'Some string.'
# The original object that `restore` was bound to is unaffected.
restore = 'Some string.'

Итак, в вашей функции, когда вы говорите:

restore = []

Вы фактически связываете восстановление с новым создаваемым объектом списка. Поскольку Python имеет функционально-локальную область видимости, restore в вашем примере это привязка локального идентификатора функции restore в новый список. Это не изменит ничего, что вы передаете setEqual как восстановить. Например,

test_variable = 1
setEqual(test_variable, [1, 2, 3, 4])
# Passes, because the identifier test_variable
# CAN'T be rebound within this scope from setEqual.
assert test_variable == 1 

Проще говоря, вы можете связывать только идентификаторы в текущей выполняемой области действия - вы никогда не сможете написать такую ​​функцию, как def set_foo_to_bar(foo, bar) это влияет на область за пределами этой функции. Как говорит @Ignacio, вы можете использовать что-то вроде функции копирования, чтобы перепривязать идентификатор в текущей области видимости:

original = [1, 2, 3, 4]
backup = list(original) # Make a shallow copy of the original.
backup.remove(3)
assert original == [1, 2, 3, 4] # It's okay!

Ты хочешь copy.deepcopy() за это.

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