1、问题背景
在Python中,我们经常需要存储多个对象的集合。有时,我们需要拷贝这些对象,以便在不修改原始对象的情况下对它们进行操作。例如,在下述代码中,我们在colors列表中存储了多个Color对象,然后我们创建一个新的列表tmp_colors来存储colors的副本。
class Color:
def __init__(self, num, nodelist):
self.num = num
self.nodelist = nodelist
def funcA():
nodeCount = 2
colors = []
for i in range(0, nodeCount):
colors.append(Color(i, [i * 10, i * 10 + 1]))
colors[0].num = 2
colors[0].nodelist = [10,20]
colors[1].num = 3
colors[1].nodelist = [23,33, 43]
tmp_colors = list(colors)
tmp_colors[0].num = 2
tmp_colors[0].nodelist = [10,21]
print("colors")
for i in range(0, nodeCount):
print(colors[i].items())
print("\ntmp_colors")
for i in range(0, nodeCount):
print(tmp_colors[i].items())
预期结果是tmp_colors和colors是独立的列表,修改tmp_colors不会影响colors。但是,运行代码后,我们发现tmp_colors[0]和colors[0]指向同一个对象,修改tmp_colors[0]也会修改colors[0]。
colors
[('num', 2), ('nodelist', [10, 20])]
[('num', 3), ('nodelist', [23, 33, 43])]
tmp_colors
[('num', 2), ('nodelist', [10, 21])]
[('num', 3), ('nodelist', [23, 33, 43])]
2、解决方案
为了解决这个问题,我们需要创建一个Color对象的真正的副本。我们可以使用copy.deepcopy()函数来做到这一点。copy.deepcopy()函数将创建一个对象的新副本,该副本与原始对象完全独立。
import copy
tmp_colors = copy.deepcopy(colors)
tmp_colors[0].num = 2
tmp_colors[0].nodelist = [10,21]
print("colors")
for i in range(0, nodeCount):
print(colors[i].items())
print("\ntmp_colors")
for i in range(0, nodeCount):
print(tmp_colors[i].items())
现在,tmp_colors和colors是独立的列表,修改tmp_colors不会影响colors。
colors
[('num', 2), ('nodelist', [10, 20])]
[('num', 3), ('nodelist', [23, 33, 43])]
tmp_colors
[('num', 2), ('nodelist', [10, 21])]
[('num', 3), ('nodelist', [23, 33, 43])]
如果我们想以后更新colors[0],我们可以通过将tmp_colors[0]的值赋给colors[0]来实现。
colors[0] = tmp_colors[0]
代码示例:
class Color:
def __init__(self, num, nodelist):
self.num = num
self.nodelist = nodelist
def funcA():
nodeCount = 2
colors = []
for i in range(0, nodeCount):
colors.append(Color(i, [i * 10, i * 10 + 1]))
colors[0].num = 2
colors[0].nodelist = [10,20]
colors[1].num = 3
colors[1].nodelist = [23,33, 43]
tmp_colors = copy.deepcopy(colors)
tmp_colors[0].num = 2
tmp_colors[0].nodelist = [10,21]
print("colors")
for i in range(0, nodeCount):
print(colors[i].items())
print("\ntmp_colors")
for i in range(0, nodeCount):
print(tmp_colors[i].items())
colors[0] = tmp_colors[0]
print("\ncolors <<< have been changed")
for i in range(0, nodeCount):
print(colors[i].items())
funcA()
结果:
colors
[('num', 2), ('nodelist', [10, 20])]
[('num', 3), ('nodelist', [23, 33, 43])]
tmp_colors
[('num', 2), ('nodelist', [10, 21])]
[('num', 3), ('nodelist', [23, 33, 43])]
colors <<< have been changed
[('num', 2), ('nodelist', [10, 21])]
[('num', 3), ('nodelist', [23, 33, 43])]