最近在备课一个AI的俄罗斯方块项目,在模拟填充加权计算环节,遇到了一个列表变量赋值、浅拷贝、深拷贝的问题,方便理解,以下对场景做简化。
class A: def __init__(self, data = None): if data == None: data = [] self.data = data def add(self, var): self.data.append(var) obj1 = A([1, 2, 3]) print(obj1.data) # 输出:[1, 2, 3] obj2 = A(obj1.data) obj2.add(4) # 对obj2.data添加元素 print(obj2.data) # 输出 [1, 2, 3, 4] print(obj1.data) # 输出 [1, 2, 3, 4]
以上是原始场景,bug出现在最后一行,当对obj2添加元素后,obj1.data 也会跟着变化,但初始目的是只传参,不想改变 obj.data 的原始值。
问题出现的原因是 obj2 = A(obj1.data) 实例化obj2时,其实是将 obj1.data 赋值给__init__的参数data,相当于obj2.data = obj1.data。
这样就出现了变量赋值引用,两个值其实是指向同一个地址的问题。
class A: def __init__(self, data = None): if data == None: data = [] self.data = data def add(self, var): self.data.append(var) obj1 = A([1, 2, 3]) print(obj1.data) # 输出:[1, 2, 3] obj2 = A(obj1.data.copy()) # 或者 obj2 = A(list(obj1.data)) obj2.add(4) # 对obj2.data添加元素 print(obj2.data) # 输出 [1, 2, 3, 4] print(obj1.data) # 输出 [1, 2, 3, 4]
以上是改进方案,用浅拷贝的方式,使其指向不同地址,看上去像解决了问题。但之后我又遇到了,一个二维列表修改元素的问题。
class A: def __init__(self, data=None): if data == None: data = [] self.data = data def setVal(self, x, y, var): self.data[x][y] = var obj1 = A([[0] * 3 for _ in range(3)]) print(obj1.data) #输出 [[0, 0, 0], [0, 0, 0], [0, 0, 0]] obj2 = A(obj1.data) obj2.setVal(1, 1, 1) print(obj2.data) #输出 [[0, 0, 0], [0, 1, 0], [0, 0, 0]] print(obj1.data) #输出 [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
可以看到,在对 obj2.setVal() 之后,对 obj1.data 也会产生影响,所以浅拷贝只复制父对象就不够了,得用深拷贝才能解决,代码如下。
import copy class A: def __init__(self, data=None): if data == None: data = [] self.data = data def setVal(self, x, y, var): self.data[x][y] = var obj1 = A([[0] * 3 for _ in range(3)]) print(obj1.data) #输出 [[0, 0, 0], [0, 0, 0], [0, 0, 0]] obj2 = A(copy.deepcopy(obj1.data)) #深拷贝 obj2.setVal(1, 1, 1) print(obj2.data) #输出 [[0, 0, 0], [0, 1, 0], [0, 0, 0]] print(obj1.data) #输出 [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Python这个语言挺有意思,一个拷贝的事整这么花哨,得处处小心。
解决方案参考:https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html
本文为 陈华 原创,欢迎转载,但请注明出处:http://ichenhua.cn/read/195
- 上一篇:
- 垂杨柳医院驾驶证体检和网上换证经历
- 下一篇:
- 通达信软件指标公式基本介绍