Python - 更改从字典初始化的对象属性会影响原始字典?



我有一个类,其属性基于用户定义的字典初始化(使用 JSON 读入(:

class Knight(object):
def __init__(self, traits):
for k, v in traits.items():
self.__setattr__(k, v)
traitfile = json.load(open(input(), 'r'))
# Where the input file is e.g. 
# {'helmet': 'horned', 
#  'sword': 'big', 
#  'words': ['Ni!', 'Peng', 'Neee-Wom!']}

当我实例化对象时,helmetswordwords按预期成为属性。但是,如果我随后更改实例属性,它似乎会影响最初初始化对象的原始字典:

tall_knight = Knight(traitfile)
print(tall_knight.words) # prints ['Ni!', 'Peng', 'Neee-Wom!']
print(traitfile['words']) # also prints ['Ni!', 'Peng', 'Neee-Wom!']
tall_knight.words.append('Ekke ekke!')
print(tall_knight.words) # prints ['Ni!', 'Peng', 'Neee-Wom!', 'Ekke ekke!'] as expected
print(traitfile['words']) # also prints ['Ni!', 'Peng', 'Neee-Wom!', 'Ekke ekke!'] NOT EXPECTED

我没想到对对象属性的更改会影响初始化它的字典。我认为实例化的全部意义在于实例是它自己的实例!这是怎么回事?!(我怎样才能阻止它?

您的问题是traitfile['words']是一个列表,当您将其复制到tall_knight.words时,您正在复制对列表的引用,而不是其中的值。所以当你修改tall_knight中的列表时,你也会修改traitfile['words']中的值。您可以通过使用以下copy.copy(如果值可能嵌套,则copy.deepcopy(复制对象中的值来解决此问题:

import copy()
class Knight(object):
def __init__(self, traits):
for k, v in traits.items():
self.__setattr__(k, copy.copy(v))

由于列表在 python 中是可变对象,因此当您创建对象时,引用在幕后将是相同的,因此您需要调用 list.copy((,它将创建一个具有不同引用的副本,然后您的更改将不会反映在原始文件中。

first_list = {"a":1, "b":[2,3,4]}
second_list = first_list
second_list["b"].append(34)
print("first one: ", first_list)
print("second one: ", second_list)

输出:

first one:  {'a': 1, 'b': [2, 3, 4, 34]}
second one:  {'a': 1, 'b': [2, 3, 4, 34]}

因此,避免更改为原始版本更好的方法是使用 copy 函数:second_list = first_list.copy((

根据您的情况包括更多内容,您还需要在更改对象之前创建副本:

import copy
class Knight(object):
def __init__(self, traits):
for k, v in traits.items():
self.__setattr__(k, copy.deepcopy(v))
traitfile = json.load(open(input(), 'r'))

以下是供参考的链接:可变和不可变数据类型

相关内容

  • 没有找到相关文章

最新更新