1、问题背景
在Python中,我们经常需要存储多个对象的集合。有时,我们需要拷贝这些对象,以便在不修改原始对象的情况下对它们进行操作。例如,在下述代码中,我们在colors列表中存储了多个Color对象,然后我们创建一个新的列表tmp_colors来存储colors的副本。
class Color:def __init__(self, num, nodelist):self.num = numself.nodelist = nodelistdef funcA():nodeCount = 2colors = []for i in range(0, nodeCount):colors.append(Color(i, [i * 10, i * 10 + 1]))colors[0].num = 2colors[0].nodelist = [10,20]colors[1].num = 3colors[1].nodelist = [23,33, 43]tmp_colors = list(colors)tmp_colors[0].num = 2tmp_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 copytmp_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 = numself.nodelist = nodelistdef funcA():nodeCount = 2colors = []for i in range(0, nodeCount):colors.append(Color(i, [i * 10, i * 10 + 1]))colors[0].num = 2colors[0].nodelist = [10,20]colors[1].num = 3colors[1].nodelist = [23,33, 43]tmp_colors = copy.deepcopy(colors)tmp_colors[0].num = 2tmp_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])]