我有一个基于用户定义字典(使用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!']}
当我实例化该对象时,helmet
、sword
和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
我没想到对对象属性的更改会影响初始化它的字典。我认为实例化的全部要点是,这个实例是它自己的实例!这是怎么回事?!(我怎样才能阻止它?)
您的问题是} (或者
traitfile['words']
是一个列表,当您将它复制到tall_knight.words
时,您复制的是对列表的引用,而不是列表中的值。因此,当您修改tall_knight
中的列表时,也会修改traitfile['words']
中的值。您可以通过使用^{copy.deepcopy
,如果值可以嵌套),在对象中创建值的副本来解决此问题:因为list在python中是可变对象,所以当您创建一个对象时,引用在场景后面是相同的,所以您需要调用list.copy(),它将创建一个具有不同引用的副本,那么您的更改将不会反映在原始副本中
输出:
因此,最好使用copy函数:second_list=first_list.copy()来避免对原始列表的更改
根据您的情况包括更多内容您还需要在更改对象之前创建副本:
以下是供参考的链接:Mutable and Immutable datatypes
相关问题 更多 >
编程相关推荐