python 赋值, 浅拷贝, 深拷贝
先放一段代码
list = [1,2,3,4,[1,2,3]]
list_1 = list #赋值
list_2 = list[:] #浅拷贝
list_3 = list.copy() #浅拷贝
list[0] = 'a'
print(list)
print(list_1)
print(list_2)
print(list_3)
list[4][0] = 'a'
print(list)
print(list_1)
print(list_2)
print(list_3)
输出
C:\Users\Mk\Anaconda3\python.exe C:/Users/Mk/PycharmProjects/untitled1/hello.py
[‘a’, 2, 3, 4, [1, 2, 3]]
[‘a’, 2, 3, 4, [1, 2, 3]]
[1, 2, 3, 4, [1, 2, 3]]
[1, 2, 3, 4, [1, 2, 3]]
[‘a’, 2, 3, 4, [‘a’, 2, 3]]
[‘a’, 2, 3, 4, [‘a’, 2, 3]]
[1, 2, 3, 4, [‘a’, 2, 3]]
[1, 2, 3, 4, [‘a’, 2, 3]]
Process finished with exit code 0
·················································
1.对于赋值,就是把原来的数据又加了一个名字,数据存放的地址没有变所以当数据发生变化时,list_1也变化了
2.对于浅拷贝即list_2,list_3, 两者把数据拷贝到另一个储存地址,所以对list的改变不会使list_2,3改变。而我们发现对于list中的元素[1,2,3]进行操作时,list_2,3发生了改变。为了搞懂其中的变化,我们可以做个试验。
list = [1,2,3,4,[1,2,3]]
list_2 = list[:]
print(id(list)) #id函数可以当做获取地址相当于cpp中的&
print(id(list_2))
print(id(list[4]))
print(id(list_2[4]))
输出:
C:\Users\Mk\Anaconda3\python.exe C:/Users/Mk/PycharmProjects/untitled1/hello.py
2080641427720
2080641427976
2080641428232
2080641428232
Process finished with exit code 0
··················································
从结果中可以看出,浅拷贝仅另存的list 而没有对其中的元素的地址做变动。
我猜测,python对list的浅拷贝的实现可能是利用了元素的id。我们再做一个实验,改变list中list[4][0]看看list[4]的id会不会改变
list = [1,2,3,4,[1,2,3]]
print(id(list[4]))
print(id(list[4][0]))
list[4][0] = 'a'
print(id(list[4]))
print(id(list[4][0]))
看输出
C:\Users\Mk\Anaconda3\python.exe C:/Users/Mk/PycharmProjects/untitled1/hello.py
1994639780616
1801940032
1994639780616
1994636984248
Process finished with exit code 0
···································
就是这样的list[4]的地址没有变化,而list[4][0]的地址变化了,而浅拷贝只能避免因list的元素的变化而变化
无法避免list的元素的元素,即其子集的元素的变化。
那么怎么进行深拷贝呢?
可以用copy方法中的deepcopy。
总结一下,赋值相当于起个别名,像古人的字和名,浅拷贝相当于另存为,你改变原文件的内容不会使新文件变化,反之亦然,但是你不能把人家里引用的网页封了,不然两文件都会打不开这个网站。深拷贝就像分出来一个平行世界,从此互不干涉