gpt4 book ai didi

python - 当字典被覆盖时如何修复类变量/常量?

转载 作者:行者123 更新时间:2023-12-01 01:20:45 28 4
gpt4 key购买 nike

我是 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'}

我很确定有一个非常简单的解决方案,但不知何故我陷入了困境......

感谢任何帮助。

最佳答案

你需要明白什么

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:正如您可能注意到的,名称类 namespace 中的 DEFAULT_SETTINGS 可以通过实例访问,即

self.DEFAULT_SETTINGS

而不是

TestClass.DEFAULT_SETTINGS

我建议对Python的不可变和可变类型、就地修改、命名空间和名称解析、继承等进行一些研究

关于python - 当字典被覆盖时如何修复类变量/常量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53868118/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com