Копирование словаря с вложенным списком и кортежем
Основной вопрос: Почему в копии словаря 'new_var' значение словаря 'var' в индексе '[0]', 'list', меняется, а в '[1]', 'tuple', нет? Ведь оба параметра в данном примере идут как вложения и что бы они не менялись, нужно использовать 'deepcopy'. В чем моя ошибка?
Весь код:
var = {'list': [[1, 2], ['a', 'b']], 'tuple': ('foo', 'bar', )}
new_var = var.copy()
var.update({'str': 'string'})
var['list'].append ([True, False])
var['tuple'] += ('baz', )
Идем пошагово.
Есть словарь:
var = {'list': [[1, 2], ['a', 'b']], 'tuple': ('foo', 'bar', )}
Создаем его копию (не глубокую):
new_var = var.copy()
Делаем 'var.update'
var.update({'str': 'string'})
Получаем 'var' и 'new_var':
{'list': [[1, 2], ['a', 'b']], 'tuple': ('foo', 'bar'), 'str': 'string'}
{'list': [[1, 2], ['a', 'b']], 'tuple': ('foo', 'bar')}
'var' обновился со значением '{'str': 'string'}', а 'new_var' остался без изменений, т.к. это копия.
Далее делаем '.append':
var['list'].append ([True, False])
Получаем 'var' и 'new_var':
{'list': [[1, 2], ['a', 'b'], [True, False]], 'tuple': ('foo', 'bar'), 'str': 'string'}
{'list': [[1, 2], ['a', 'b'], [True, False]], 'tuple': ('foo', 'bar')}
Первый вопрос: Почему значение листа '[True, False]' было перенесено в копию 'new_var'? (Полагаю потому, что это вложение в виде ссылки)
Далее добавляем пункт в 'tuple':
var['tuple'] += ('baz', )
Получаем 'var' и 'new_var':
{'list': [[1, 2], ['a', 'b'], [True, False]], 'tuple': ('foo', 'bar', 'baz'), 'str': 'string'}
{'list': [[1, 2], ['a', 'b'], [True, False]], 'tuple': ('foo', 'bar')}
Второй вопрос: Почему в этом случае 'baz' добавилось только в словарь 'var', но не в его копию 'new_var', как это было в прошлом пункте?
P.S. Вероятно, мой вопрос глупый, я только учусь.
Ответы (1 шт):
Разница в том, что tuple в Python является неизменяемым (immutable) объектом . Поэтому для кортежей не существует метода .append() и вам пришлось заменить значение по ключу "tuple" ссылкой на новый кортеж.
Ваш пример:
Out[321]:
{'list': [[1, 2], ['a', 'b'], [True, False]],
'tuple': ('foo', 'bar'),
'str': 'string'}
In [322]: id(var["tuple"])
Out[322]: 140364687889408
In [323]: var['tuple'] += ('baz', )
In [324]: id(var["tuple"])
Out[324]: 140364687888704 # <--- обратите внимание на изменившийся `id` !
In [325]: var
Out[325]:
{'list': [[1, 2], ['a', 'b'], [True, False]],
'tuple': ('foo', 'bar', 'baz'),
'str': 'string'}
In [326]: id(new_var["tuple"])
Out[326]: 140364687889408 # <-- new_var["tuple"] все еще указывает на кортеж __до__ изменения
var['tuple'] += ('baz', ) эквивалентно:
var['tuple'] = var['tuple'] + ('baz', )
А var['tuple'] + ('baz', ) создает новый кортеж с результатом сложения.