python中的浅拷贝和深拷贝

时间:2025-01-19 21:36:33

1、赋值语句

 a = 'abc'
b = a
print id(a)
print id(b) # id(a):29283464
# id(b):29283464

通过简单的复制,我们可以看到,a b其实是一个对象。

对象赋值实际上是简单的对象引用,也就是说,当你创建了一个对象,然后把它赋值给另一个变量时,python并没有拷贝这个对象,而是拷贝了这个对象的引用。

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwEAAADQCAIAAADQ9/pVAAASqUlEQVR4nO3daXOU55XGcX0ufQF/iFRNpfyiZTBmiMtJZiYOIYOJybhmRpnJxPGATdJIMhiziwZG2OwYY5aADe5FtFor2le09jYvmkVhF/fTz9X3uf+/ul5hCrp8jg5X6ZHUTVUAAIDwNKlfAAAAgAAdCAAAhIgOBAAAQkQHAgAAIaIDAQCAENGBAABAiOhAAAAgRHQgAAAQIjoQAAAIER0IAACEiA4EAABCRAcCAAAhogMBAIAQ0YEAAECI6EAAACBEdCAAABAiOhAAAAgRHQgAAISIDgQAAEJEBwIAACGiAwEAgBDRgQAAQIjoQAAAIER0IAAAECI6EAAACBEdCAAAhIgOBAAAQkQHAgAAIaIDAQCAENGBAABAiOhAAAAgRHQgAAAQIjoQAAAIER0IAACEiA4EAABCRAcCAAAhogMBAIAQ0YEAAECI6EAAACBEdCAAABAiOhAAAAgRHQgAAISIDgQAAEJEBwIAACGiAwEAgBDRgQAAQIjoQAAAIER0IAAAECI6EAAACBEdCAAAhIgOBAAAQkQHAgDE7Sc7bpO6Rj1hP9CBAABxk1cE81FP2A90IFfyRTcf9YQBRE9+WMxHPWE/0IFcyRfdfNQTBhA9+WExH/WE/UAHciVfdPNRTxhA9OSHxXzUE/YDHciVfNHNRz1hANGTHxbzUU/YD3QgV/JFNx/1hAFET35YzEc9YT/QgVzJF9181BMGED35YTEf9YT9QAdyJV9081FPGED05IfFfNQT9gMdyJV80c1HPWEA0ZMfFvNRT9gPdCBX8kU3H/WEAURPfljMRz1hP9CBXMkX3XzUEwYQPflhMR/1hP1AB3IlX3TzUU8YQPTkh8V81BP2Ax3IlXzRzUc9YQDRkx8W81FP2A90IFfyRTcf9YQBRE9+WMxHPWE/0IFcyRfdfNQTBhA9+WExH/WE/UAHciVfdPNRTxhA9OSHxXzUE/YDHciVfNHNRz1hANGTHxbzUU/YD3QgV/JFNx/1hAFET35YzEc9YT/QgVzJF9181BMGED35YTEf9YT9QAdyJV9081FPGED05IfFfNQT9gMdyJV80c1HPWEgErnW5qZHEin1y1GTHxbzUU/YD3QgV/JFNx/1hAF3udbmx70n19rc1NTcmpO+IjX5YTEf9YT9QAdyJV9081FPGIharrV5jZ8K+mHw/kqpUrcXJCA/LOajnrAf6ECu5ItuPuoJA5H4u2dha3ocVipXPjrRu74t8+XV0an5Yj1fZHzkh8V81BP2Ax3IlXzRzUc9YcBdKrG69az980DVanVoevmvl+61JNP/8/VA98hC5C8xZvLDYj7qCfuBDuRKvujmo54w4OyJ0vNaHahmYaV84oeJd/fmNh/KX8hN+/uATH5YzEc9YT/QgVzJF9181BMG3K3+PNCDh2Iu3xpWqVRv9M39/njv+rbM/muj0wv+PSCTHxbzUU/YD3QgV/JFNx/1hIEopBKrvhIolYjo2+MHp5b+cvFeSzL9p9MD3aM+PSCTHxbzUU/YD3QgV/JFNx/1hIFGN79cPvH9xLt7c5sP5y92TxfLHjwgkx8W81FP2A90IFfyRTcf9YQBP9QekG1P9b7d7sEDMvlhMR/1hP1AB3IlX3TzUU8Y8MzqB2R3G/UBmfywmI96wn6gA7mSL7r5qCcMeGl+uXz8+4mf7cn95nD+UuM9IJMfFvNRT9gPdCBX8kU3H/WEAY+VK9XrvbMfpgob2jMHrjfQAzL5YTEf9YT9QAdyJV9081FPGLBgcGpp18WhlmT649MD+TH9AzL5YTEf9YT9QAdyJV9081FPGLBjfrmU+n78Z3tyW9QPyOSHxXxUk/ULHciVfNHNRz1hwJpypXrt4QOyg6IHZPLDYj7xz9RHdCBX8kU3H/WEAbMGppZ2XRhqSaY/PjOQH1uM86+WHxbziXOa/qIDuZIvuvmoJwwYd3+plLo1vmlPdsuRnm/uzpRieUAmPyzmE8MQDaADuZIvuvmoJwwEoVypXivM/u5YYUNH5uD1sZk6PyCTHxbzqev4zKADuZIvuvmoJwyEpX9y6bMLQ4lk+s9nBnvq9oBMfljMp06DM4YO5Eq+6OajnjAQovtLpWO3xjftyf72SM/lOjwgkx8W84l2XlbRgVzJF9181BMGwlWuVK8WZrcdK2zoyBy6MTazWIrqT5YfFvOJalK20YFcyRfdfNQTBlDtn1z69PxQIpn+5Oxgz/irPiArlSvP+8Z7+WExn+iGbxkdyJV80c1HPWH4p1JtrPfGMmNuqdR5a/wfP8/+69FXekBWGF98pyM7+6zPHskPi/nUZwWsoQO5ki+6+agnDP8cv7O7VG6UN8ay58EDss7COx3Zwy97QNZ+efijE71PdyX5YTGf+i2AJXQgV/JFNx/1hOGf7V2JXZe3UoPqrW/i5Q/IiuXK5kP51K3xJ35dfljMp/7zt4AO5Eq+6OajnjD8s2n/G5v2v0ENisfcUqnz5oMHZN/mn/GAbHR2Zd3udPfo371Rq/ywmE+MK+AxOpAr+aKbj3rC8M+2k29Sg2JWKle+65n9oLOwsSN7+G9jT3wN0JX8zKY92fnlx78oPyzmE/sKeIkO9CIT91fuTS+/+PfIF9184pk1LNneldh28s1dl7dSg+LXO7G48/xQIpn+37ODhVUPyHZdHPrDqf5HnyOSHxbzkUzfO3SgF7k1MNeSTLdfHp5fLj/v98gX3XzinDhs2N6V2N6VKJWL1CCVuaXS0ZvjGz/Pbj3acyU/UypXVkqVf95/99SdydpvkB8W89EugC/oQC8xvVD85Ozg+rbM2cxU5VnfBypfdPOJfebwXq0DVatVapBWqVy50jPzQWfPxo7skb+NZUcW3tqd7p1YrHI5uZyNgQ70SrpHFzYfzv/6UD43svDEf5IvuvlIJh6hnZe21P5JJrFl0/43ah2oSg1qDL0TizvODSaS6Z9+ducnO24vrpTlh8V81DP3Q8wdKNfa3PRIIhXvX+6mUqmez06/3Z75+MzA1PzjSypfdPMRDj0Sj/5JJnFm56Utj0ZADYrTjnODfzjVv+PcYNvl4f3XRw9dH9t3daT923ufnh/anirUPqi3dhbkh8V81Ivghzg7UK61+XHvybU2NzU1t+Zi/PujsLBS7vh2uCWZPnpzfKVUqdKB+Eh+mdo/yepXETpqUGy+uDry4fHCL7+8u64t8w+f3vnpZ3dakum32zMbO7IbOzK1D+qf78vJD4v5qBfBD7pnYbnW5jV+Kmj/tdEGyR+/Hqgt2Y2+Ofmim0/dVjAmdKAGQQ2Kx6k7k113Jm/0zQ1MLS2uPP5ukpv9c5sP5Wsf1JPzRflhMR/hDnhE+SxsrY/D5NVnVQfqry0ZHYiP5JeiAzUOapDE9wP3txzp+cW+7kvdM786cPd0eqrKZ9C5nI0hzg6USqxuPWv/PFAjWFgpd1webkmmO2+OF8s8C+Mj+eXoQA2FGhSnO0PzW4/2vPdF7lL3dKVS7bw5vu1Yofaf5IfFfLSj90WMHeiJ0uNbB6pUqueyU2+3Z/58ZpCvieYj+dXRgRpNqVzceWlLrQaVKy96v0+8tszw/LbOwrt7c+dz07U3zxieWW5JpodnHvzUWflhMR/l+P2h+jzQg4divnSg7tGFzYfyvz6U7+Z74/lIXiM6UKNZ1YE+oANFLjey8GGqsGlP9kxmavV7h207Vuhc9c6p8sNiPorh+yferwdKJVZ9JVAq4UMH4mckyhP7zCNGB2ooPAurn/zYwr+d6N34efarHyefeOfU0+mp9w/mV/+a/LCYT9zj9xM/I/FFau+V0XF5eGGF98rgI/k10YEaBwWoTgrji/9+su+djmzX7cniU+8bP71QXPfwx0M/Ij8s5hPj/D1GB3oR3jO1ERLPrOuHDtQgKED10Dex9J9dfRvaMyd+mKj9yLSntZ7q3/vdyBO/KD8s5lP/4VtAB3IlX3TzUU/YFR2oEVCAIjcwtfRfp/rXt2VSt8aXi89uP9Vq9bue2fe+yD1dj+SHxXzqPH8j6ECu5ItuPuoJu9rOe2Uowntl1M/Q9PIfvx5Y15Y5enN8ufjcrxOoOZOZevpbSapcTi5nY6ADuZIvuvmoJ+yK90yNP7xnap0Mzyx/fHpg3e704Rtji8//KslXIT8s5hPV0G2jA7mSL7r5qCcM/9SaUJUCFJ3R2ZVPzg6+tTt94ProC75H5NXJD4v5uM8oBHQgV/JFNx/1hOGfWgeiAEVifG5l5/mhlmR639WR+eXIfpyS/LCYT1STso0O5Eq+6OajnjD8s70rse3kmxQgR5P3i7suDLUk03uujMwtRfzDJOWHxXyinZdVdCBX8kU3H/WE4Z9tJ9/ctP8NCtBrm5ov/vXSvdpPR5tZrMuP0pYfFvOpx9TsoQO5ki+6+agnDP9QgF7bzEKx7ZvhlmR69zf3phfq+H9PfljMp36zs4QO5Eq+6OajnjD8s70rQQFaq9nFUse3wy3J9F8u3lv9ttB1Ij8s5lPvCdpAB3IlX3TzUU8Y/jl+ZzcF6NXNLZX2XhlpSaY/uzA0cX8lnr9UfljMJ545+o4O5Eq+6OajnjD8U6k+98cWY7X55dK+q6MtyfSOc4NjczG1nxr5YTGfOKfpLzqQK/mim496woBBCyvlA9dH39qd/uTs4MjsS94VsR7kh8V84p+pj+hAruSLbj7qCQOmLK6UD98YW7c7/afTAy99T+j6kR8W81FN1i90IFfyRTcf9YQBI5aL5aM3x9e1Zf77q/7BqSXti5EfFvPRztcXdCBX8kU3H/WEAe8tFyupW+Pr2zKtp/r7J8Xtp0Z+WMxHPWE/0IFcyRfdfNQTBjy2Uqqc+GFiQ3vmP/6vr3diUf1yHpMfFvNRT9gPdCBX8kU3H/WEAS8Vy5Wu25PvdGQ/OtHbM9ZA7adGfljMRz1hP9CBXMkX3XzUEwY8UypXvvpxcuPn2d8f7+0eXVC/nGeTHxbzUU/YD3QgV/JFNx/1hAFvlMqVM5mpTXuyvztWyA7Pq1/Oi8gPi/moJ+wHOpAr+aKbj3rCQDRSiaam5tZcff7wcqV6Pjv97t7cB509P95r6PZTIz8s5qOesB/oQK7ki24+6gkD0ahTB6pUqhe7p9/7IvfbIz23B+9H/cfXi/ywmI96wn6gA7mSL7r5qCcMRCPyDlSpVi/fnfnFvu7fHM7fGpiL7g+Og/ywmI96wn6gA7mSL7r5qCcMRCPCDlSpVq/0zPzT/u73D+Zv9HnWfmrkh8V81BP2Ax3IlXzRzUc9YSAaDzpQKtH0UCL1On/OtcLsrw7c/ZcDd68WZqN+jfGRHxbzUU/YD3QgV/JFNx/1hIFoPCg/Dz8VlGttXuvnhW70zb1/MP/LL7uv5Gcq9XmRsZEfFvNRT9gPdCBX8kU3H/WEgWg89SxsDQ/HiuXKliM9P9/X/c1d79tPjfywmI96wn6gA7mSL7r5qCcMROOpypNrbV7D87D0vfmKjfpTrVa5nFzOxkAHciVfdPNRTxiIhmMHMkZ+WMxHPWE/0IFcyRfdfNQTBqLh8izMHvlhMR/1hP1AB3IlX3TzUU8YiMYTXxOdSrz2d4ZZID8s5qOesB/oQK7ki24+6gkD0UglmpoSqVxr88NvjQ/2c0DVKpeTy9kY6ECu5ItuPuoJA4ie/LCYj3rCfqADuZIvuvmoJwwgevLDYj7qCfuBDuRKvujmo54wgOjJD4v5qCfsBzqQK/mim496wgCiJz8s5qOesB/oQK7ki24+6gkDiJ78sJiPesJ+oAO5ki+6+agnDCB68sNiPuoJ+4EO5Eq+6OajnjCA6MkPi/moJ+wHOpAr+aKbj3rCAKInPyzmo56wH+hAruSLbj7qCQOInvywmI96wn6gA7mSL7r5qCcMIHryw2I+6gn7gQ7kSr7o5qOeMIDoyQ+L+agn7Ac6kCv5opuPesIAoic/LOajnrAf6ECu5ItuPuoJA4ie/LCYj3rCfqADuZIvuvmoJwwgevLDYj7qCfuBDuRKvujmo54wAMAmOpAreUUwH/WEAQA20YEAAECI6EAAACBEdCAAABAiOhAAAAgRHQgAAISIDgQAAEJEBwIAACGiAwEAgBDRgQAAQIjoQAAAIER0IAAAECI6EAAACBEdCAAAhIgOBAAAQkQHAgAAIaIDAQCAENGBAABAiOhAAAAgRHQgAAAQIjoQAAAIER0IAACEiA4EAABCRAcCAAAhogMBAIAQ0YEAAECI6EAAACBEdCAAABAiOhAAAAgRHQgAAISIDgQAAEJEBwIAACGiAwEAgBDRgQAAQIjoQAAAIER0IAAAECI6EAAACBEdCAAAhIgOBAAAQkQHAgAAIaIDAQCAENGBAABAiOhAAAAgRHQgAAAQIjoQAAAIER0IAACEiA4EAABC9P8BGwnpAfqEpgAAAABJRU5ErkJggg==" alt="" width="591" height="128" />

2、浅拷贝

序列类型的对象默认类型拷贝是浅拷贝,通过以下几种方式实施:

  (1) 完全切片操作[:]

  (2) 利用工厂函数,例如list() 、dict()等

  (3) 使用copy模块中的copy函数

创建一个列表对象,然后分别用切片操作和工厂方法拷贝对象,然后使用id()内建函数来显示每个对象的标识符。

s = ['abc',['def',1]]
a = s[:]
b= list(s)
print [id(x) for x in s,a,b]
#[29262792.29238576,28957272]

可以看到创建了三个不同的列表对象。在对对象的每一个元素进行操作:

a[0] = 'a'
b[0] = 'b'
print a,b
# (['a',['def',1]],['b',['def',1]]) a[1][1] = 0
print a,b
# (['a',['def',0]],['b',['def',0]])

我们可以看到,当执行a[1][1] = 0时,b[1][1]也跟着变为0。这是因为我们仅仅做了一个浅拷贝,对一个对象进行浅拷贝其实是新创建了一个类型跟原对象一样,它的内容元素是原来对象元素的引用,换句话说,这个拷贝的对象是新的,但他的内容还是原来的。这就是浅拷贝。

但是我们看到a的第一个元素,即字符串被赋值后,并没有影响b的。这是因为在这个对象中,第一个字符串类型是不可变的,第二个列表对象是可变的。正因为如此,当进行浅拷贝时,字符串被显式的拷贝,并创建了一个新的字符串对象,而列表元素只是把它的引用复制了,并不是他的成员。

#改变前
print [id(x) for x in a]
#[29563284,27843874]
print [id(x) for x in b]
#[29563284,27843874] #改变后
print [id(x) for x in a]
#[23464734,27843874]
print [id(x) for x in b]
#[29884656,27843874]

3 深拷贝

根据上面的例子,如果我们想要在改变a时不影响到b,要得到一个完全拷贝或者说深拷贝(一个新的容器对象,包含原有对象元素全新拷贝的引用),就需要copy.deepcopy()函数。

import copy
s = ['abc',['def',1]]
a = copy.deepcopy(s)
b = copy.deepcopy(s)
print [id(x) for x in s,a,b]
#[29278336,29262792,29238576] a[0] = 'a'
b[0] = 'b'
a[1][1] = 0
print a,b
#(['a',['def',0]],['b',['def',1]])

需要注意的是:第一,非容器类型(比如数字、字符串和其他“原子”类型的对象,像代码、类型和xrange对象等)没有拷贝一说,浅拷贝是用完全切片操作来完成的。

       第二:如果元组变量只包含原子类型对象,对他的拷贝将不会进行,即使使用深拷贝操作也只能得到一个浅拷贝。