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

TY *_*Lim 1 python dictionary python-3.x

我有一个类,其属性基于用户定义的字典初始化(使用 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!']}
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*ick 5

您的问题是,这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))
Run Code Online (Sandbox Code Playgroud)