Вам необходимо понять, что делает
self.settings = TestClass.DEFAULT_SETTINGS
.
Оператор делает settings
именем в пространстве имен экземпляра.И он указывает на тот же объект, на который указывает имя DEFAULT_SETTINGS
в пространстве имен класса.
Это означает, что оператор не создает новый объект.
Примечание: этобывает и для self.string
.Но в этом случае self.string
является строкой, которая является неизменной.Это означает, что когда вы назначаете новое значение тому же имени, создается новый объект.
Давайте рассмотрим пример:
>>> class C:
... S = 'asdasd'
...
>>> o = C()
>>> o.s = C.S
>>> o.s
'asdasd'
>>> o.s is C.S
True
>>> o.s = 'pasdpdspa'
>>> o.s is C.S
False
>>> o.s = C.S
>>> C.S = 'popopo'
>>> o.s
'asdasd'
С другой стороны, словарь является изменяемыми модифицируется на месте.
Итак, как предлагается в комментариях, чтобы заставить его работать, вам необходимо скопировать такой словарь, например, с
self.settings = dict(TestClass.DEFAULT_SETTINGS))
или еще лучше с
from copy import deepcopy
self.settings = deepcopy(self.DEFAULT_SETTINGS)
Примечание: последнее необходимо, если словарь вложен.dict
делает только поверхностную копию, поэтому она не будет работать во всех случаях.
Покажем это на примере:
>>> d = {1:10, 2: {21: 'abc', 22: 'def'}}
>>> d
{1: 10, 2: {21: 'abc', 22: 'def'}}
>>> d2 = dict(d)
>>> d is d2
False
>>> d[2] is d2[2]
True
>>> d2[2] = 99
>>> d
{1: 10, 2: {21: 'abc', 22: 'def'}}
>>> d2 = dict(d)
>>> d2[2][21] = 99
>>> d
{1: 10, 2: {21: 99, 22: 'def'}}
, тогда как
>>> d = {1:10, 2: {21: 'abc', 22: 'def'}}
>>> d2 = deepcopy(d)
>>> d2[2] is d[2]
False
>>> d2[2][21] = 99
>>> d
{1: 10, 2: {21: 'abc', 22: 'def'}}
Примечание 2: как вы можете заметить, имя DEFAULT_SETTINGS в пространстве имен класса может быть достигнуто через экземпляр, то есть
self.DEFAULT_SETTINGS
вместо
TestClass.DEFAULT_SETTINGS
Я предлагаю провести небольшое исследованиеНеизменяемые и изменчивые типы Python, модификация на месте, пространства имен и разрешение имен, наследование и т. Д.