繁体   English   中英

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

[英]Python - changing object attributes initialised from dictionary affects the original dictionary?

我有一个 class ,其属性基于用户定义的字典(使用 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!']}

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

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 ,如果值可能是嵌套的)复制 object 中的值来解决此问题:

import copy()

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

由于列表在 python 中是可变的 object ,因此当您创建 object 时,参考在幕后将是相同的,因此您需要调用 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)

Output:

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

所以最好避免对原始的更改是使用副本 function: second_list = first_list.copy()

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

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'))

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM