浅拷贝与深拷贝 - - [[0]*m]*n与[[0 for _ in range(m)] for _ in range(n)]的区别
最近刚开始转用python刷题,今天刷到718. 最长重复子数组。用了dp,又看了看评论区的代码,发现基本一样,可是结果就是不对…感觉特别懵逼,后来注意到创建dp数组的语句不太一样,就想可不可能是这个问题,一改果然对了。查看相关资料后,发现原来这是python深拷贝与浅拷贝的区别。
python的浅拷贝与深拷贝
三种方式:
a=[[0,1,2,3],[4,5,6,7],[8,9,10,11]]
b=a
c=a.copy()
d=copy.deepcopy(a)
1.直接赋值(b=a), 即对象的引用,也就是别名;
2.浅拷贝(c=a.copy), 只拷贝父对象,不会拷贝对象的内部的子对象。
(就是只拷贝了外面这一层,a[0],a[1],a[2],里面这三个里面的元素还是相当于引用。
不拷贝子对象即子对象还是引用,如果a[0][1]+=1, c即使不做操作,c打印出来c[0][1]也会变成2。再有,对于拷贝父对象就是,如果a外面这一层加了一个a[3],a.append([12,13,14,15]),c打印出来是不会加上这个[12,13,14,15]的)
3.深拷贝(d=copy.deepcopy(a))。copy模块的deepcopy方法,完全拷贝了父对象和子对象。
(就是一个全新的数组,和原来的互不相干,谁变了都不会影响谁)
示例
import copy
a=[[0,1,2,3],[4,5,6,7],[8,9,10,11]]
b=a # 直接赋值,对象的引用,相当于别名
c=a.copy() # 浅拷贝,只拷贝父对象,子对象不拷贝
d=copy.deepcopy(a) # 深拷贝,父子对象都拷贝
a[0][1]+=1
a.append([12,13,14,15])
print("a:",a) # 原数组
print("b:",b) # 引用,和a相同,a的别名
print("c:",c) # 浅拷贝,外面一层父对象是拷贝,里面的子对象不拷贝,还是引用
print("d:",d) # 深拷贝,父子对象都拷贝,相当于全新的数组,和a不相干,只是复制了a的值
输出:
a: [[0, 2, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
b: [[0, 2, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
c: [[0, 2, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
d: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
[[0]*m]*n与[[0 for _ in range(m)] for _ in range(n)]的区别
[0]*m,[[0]*m]*n属于直接赋值。所以当a[1][1]+=1时,a[0][1]即使不做操作,也会变得和a[1][1]一样。
而[[0 for _ in range(m)] for _ in range(n)]就是真正的初始化创建一个全新的数组。
l=[0]*3
print(l)
l[0]=2
print(id(l[0]),id(l[1]),id(l[2]))
print(l)
l=[[0]*3]*4
print(l)
l[0][1]+=1
print(id(l[0]),id(l[1]))
print(id(l[0][0]),id(l[0][1]),id(l[0][2]))
print(id(l[1][0]),id(l[1][1]),id(l[1][2]))
print(l)
输出:
[0, 0, 0]
140715356469088 140715356469024 140715356469024
[2, 0, 0]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
2361970042752 2361970042752
140715356469024 140715356469056 140715356469024
140715356469024 140715356469056 140715356469024
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]