2013-04-19 2 views
4

Может ли кто-нибудь объяснить, почему это произошло со списком и как очистить список после добавления в другой список?Некоторое странное поведение Список Python и dict

>>> t = {} 
>>> t["m"] = [] 
>>> t 
{'m': []} 
>>> t["m"].append('qweasdasd aweter') 
>>> t["m"].append('asdasdaf ghghdhj') 
>>> t 
{'m': ['qweasdasd aweter', 'asdasdaf ghghdhj']} 
>>> r = [] 
>>> r.append(t) 
>>> r 
[{'m': ['qweasdasd aweter', 'asdasdaf ghghdhj']}] 
>>> t["m"] = [] 
>>> r 
[{'m': []}] 
+1

Вы вызываете это поведение * странно *, предполагая, что python будет неявным образом скопировать весь словарь при добавлении 'to r. Почти в каждом случае Python ничего не делает, если вы явно не указали это. – jamylak

ответ

10

Это нормальное поведение. Python использует ссылки на элементы хранилища. Когда вы сделаете r.append(t) python будет хранить t в r. Если позднее вы измените t, то t в r также будет изменен, потому что это тот же объект.

Если вы хотите сделать t независимым от значения, хранящегося в r, его необходимо скопировать. Посмотрите на модуль copy.

1

Словари изменчивы в Python, возьмите копию вместо

>>> import copy 
>>> r.append(copy.copy(t)) 
>>> t 
{'m': ['qweasdasd aweter', 'asdasdaf ghghdhj']} 
>>> r 
[{'m': ['qweasdasd aweter', 'asdasdaf ghghdhj']}] 
>>> t["m"]=None 
>>> r 
[{'m': ['qweasdasd aweter', 'asdasdaf ghghdhj']}] 
2

При вызове r.append(t) вы говорите, «сохранить ссылку на значение, хранимое в t в конце списка r». Словарь t ссылки не копируются, поэтому при изменении t вы изменяете данные, на которые ссылается r.

Такое поведение можно увидеть более ясно здесь:

>>> x = [] 
>>> y = x 
>>> x.append(1) 
>>> y 
[1] 

Это устанавливает y к значению, на который ссылается x так, когда x изменения представляется, что y изменения, а также.

1

Вы можете попробовать сделать:

import copy 
r.append(copy.deepcopy(t)) 

и что должно работать.

Cheers

1

Это нормально. Когда вы назначаете объект переменной, python не будет копировать этот объект в вашу переменную. Он просто назначит ссылку исходного объекта на ваш новый объект.

In [1]: a = [1,2] 
In [2]: b = a 
In [3]: a.remove(1) 
In [4]: b 
Out[4]: [2] 

Здесь b будет содержать только ссылку на первоначальный список a. Если вы хотите переопределить это поведение, вы можете использовать модуль копирования.

In [7]: import copy 
In [8]: a = [1,2] 
In [9]: b = copy.deepcopy(a) 
In [10]: a.remove(1) 
In [11]: b 
Out[11]: [1, 2] 

deepcopy дублирует все, включая отдельные элементы.

Смежные вопросы