Как мне скопировать только значения, а не ссылки из списка Python? - PullRequest
0 голосов
/ 17 марта 2010

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

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

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

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

Ответы [ 2 ]

8 голосов
/ 17 марта 2010

Вы хотите copy.deepcopy() для этого.

5 голосов
/ 17 марта 2010

Первое, что нужно понять, - почему этот метод 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!
...