Вы определили mutable
и immutable
на уровне класса, поэтому оба будут общими во всех экземплярах Class
.Ответы в связанном вопросе подробно объясняют, как избежать поведения совместного использования, которое вы наблюдаете, поэтому я просто объясню, что происходит с вашим кодом.
В принципе, это совместное использование не связано с изменяемыми илинеизменяемый, но в вашем коде есть некоторые нюансы, которые могут запутать его.
В случае mutable
наблюдаемое поведение довольно легко объяснить.
Прежде всего,dict mutable
- это всегда один и тот же объект в памяти:
>>> o1, o2 = Class(), Class()
>>> o1.mutable is o2.mutable is Class.mutable
True
, когда вы изменяете каким-либо образом mutate
, это изменение будет видно везде, где содержится ссылка на этот dict.
>>> Class.mutable
{}
>>> o2.mutable[1] = 2
>>> o1.change()
>>> Class.mutable
{1: 2, 'key': 'value'}
Пока все это ожидается.Сложность с immutable
в том, что вы не изменяете Class.mutable
при изменении, вы присваиваете атрибут mutable
экземпляру (self
) change
вызывается!
Перед вызовом изменения immutable
существует только на уровне класса и доступен через класс при поиске на экземпляре o1
или o2
.(Обратите внимание, что значения в экземплярах o1
и o2
пусты.)
>>> o1, o2 = Class(), Class()
>>> o1.immutable, o2.immutable, Class.immutable
(0, 0, 0)
>>> o1.__dict__, o2.__dict__, 'immutable' in Class.__dict__
({}, {}, True)
При вызове change
для o2
атрибут immutable = 1
устанавливается только для экземпляра o2
!
>>> o2.change()
>>> o1.immutable, o2.immutable, Class.immutable
(0, 1, 0)
>>> o1.__dict__, o2.__dict__, 'immutable' in Class.__dict__
({}, {'immutable': 1}, True)
>>> o1.immutable is Class.immutable
True
>>> o2.immutable is Class.immutable
False
Важно понимать, что изменяемые и неизменяемые объекты, установленные на уровне класса, используются одинаково.Разница лишь в том, что у изменяемых объектов нет методов, которые их изменяют.Но если вы сделали self.mutable = {'key': 'value'}
в change
и затем вызвали change
в конкретном экземпляре, атрибут mutable
, определенный в экземпляре, будет иметь приоритет над атрибутом, определенным на уровне класса, при поиске в экземпляречерез точечные обозначения.