我是python的新手,它尝试使用默认值并为类实例自定义它们。
因此,在此示例中,我定义了一个DEFAULT_STRING
和一个DEFAULT_SETTINGS
变量,可以使用customize()
对其进行自定义,并且应将其重置为reset()
的默认值。
这对于DEFAULT_STRING
来说很好用。但是以某种方式customize()
会覆盖DEFAULT_SETTINGS
字典。
class TestClass:
DEFAULT_STRING = 'default string'
DEFAULT_SETTINGS = {
'key1': 'value1',
'key2': 'value2'
}
def __init__(self):
self.reset()
def customize(self):
self.string = 'custom string'
self.settings['key2'] = 'CUSTOM VALUE'
def reset(self):
self.string = TestClass.DEFAULT_STRING
self.settings = TestClass.DEFAULT_SETTINGS
test = TestClass()
test.customize()
print(test.DEFAULT_STRING) # default string
print(test.string) # custom string
print(test.DEFAULT_SETTINGS) # {'key1': 'value1', 'key2': 'CUSTOM VALUE'}
print(test.settings) # {'key1': 'value1', 'key2': 'CUSTOM VALUE'}
test.reset()
print(test.DEFAULT_STRING) # default string
print(test.string) # default string
print(test.DEFAULT_SETTINGS) # {'key1': 'value1', 'key2': 'CUSTOM VALUE'}
print(test.settings) # {'key1': 'value1', 'key2': 'CUSTOM VALUE'}
我很确定有一个非常简单的解决方案,但是我莫名其妙地陷入了困境……
感谢您的帮助。
答案 0 :(得分:2)
您需要了解什么
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_SETTINGSself.DEFAULT_SETTINGS
代替
TestClass.DEFAULT_SETTINGS
我建议对Python的不可变和可变类型,就地修改,名称空间和名称解析,继承等进行一些研究