Python - обновить словарь самостоятельного класса внутри функции класса

У меня есть словарь, объявляющий в классе (self.d1). После вызова функции f1, self.d1 нужно обновить до локального dict объявить внутри f1

import copy
class num: def __init__(self): self.d1 = {'a':1, 'b':2, 'c':3} self.f1(self.d1) print self.d1 def f1(self,d): d2 = {'d':4, 'e':5, 'f':6} d = copy.deepcopy(d2)
test = num()

Я ожидаю, что вывод будет:

{'d':4, 'e':5, 'f':6}

но выход

{'a':1, 'b':2, 'c':3}

Я хочу понять, в чем проблема, а не только решение

4 ответа

Вы не хотите назначать d в f1(), так как он теряет старую привязку, которую он должен был self.d1. Поэтому после назначения d является только локальной переменной f1().

Но вы можете достичь того, чего хотите:

class num: def __init__(self): self.d1 = {'a':1, 'b':2, 'c':3} self.f1(self.d1) print self.d1 def f1(self,d): d2 = {'d':4, 'e':5, 'f':6} d.clear() d.update(d2)
test = num()

Выход

{'e': 5, 'd': 4, 'f': 6}

Обратите внимание, что мой код не присваивает d в f1(), он делает только вызовы, которые мутируют существующий объект.

Для дополнительной справки по этой и смежным темам см. эту замечательную статью SO stalwart, Ned Batchelder: Факты и мифы о именах и значениях Python


Проблема заключается в том, что

d = deepcopy(...)

Вы не изменяете словарь, на который ссылается d, вы просто изменяете d, чтобы ссылаться на другой словарь (в данном случае на вновь созданную копию словаря).


Если вы присваиваете значение {'a' : 1} некоторой переменной self.d1, то эта переменная сохраняет ссылку на значение. Это означает, что вы можете изменить значения d1, обратившись к нему, например: self.d1['a'] = 2, и теперь значение будет {'a' : 2'}.

Вы также можете изменить ссылку переменной self.d1, присвоив ее чему-то новому. Поэтому в вашей функции f1 вы фактически изменяете ссылку, на которую указывает d, а не значение, на которое она ссылается. И из-за определения функции self.d1 по-прежнему будет ссылаться на исходное значение вне области действия.


Дайте другое объяснение...

class num: def __init__(self): self.d1 = {'a':1, 'b':2, 'c':3} # calling a function with a dictionary copies the *reference* to the # dictionary object. print 'first test ..' self.test_dict_arg_1(self.d1) print self.d1 print 'second test ...' self.test_dict_arg_2(self.d1) print self.d1 def test_dict_arg_1(self, d): d2 = {'d':4, 'e':5, 'f':6} # now you load d with a new value, the referenced object is untouched d = d2 def test_dict_arg_2(self, d): d2 = {'d':4, 'e':5, 'f':6} # now you work with the referenced object d.clear() d.update(d2)

licensed under cc by-sa 3.0 with attribution.