浅拷贝与深拷贝
最后更新于:2022-04-02 00:35:04
python中有一个模块copy,deepcopy函数用于深拷贝,copy函数用于浅拷贝。要理解浅拷贝,必须先弄清楚python中的引用。
### 引用
**Python中一切都是对象,变量中存放的是对象的引用**。这是一个普遍的法则。**可以说 Python 没有赋值,只有引用**。如,a=1,变量a只是整数对象1的引用。
####
### 可变对象与不可变对象及其引用
#### 一、不可变对象
不可变对象包括:数字,字符串,元组。
由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。运用这样的机制,有时候会让人产生糊涂,似乎可变对象变化了。如下面的代码:
~~~
i=73
i+=2
~~~
这里的‘=’表示引用。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/189afde3f9ed41abac23f0acd7b361f6_835x167.png)
从上面得知,不可变的对象的特征没有变,依然是不可变对象,变的只是创建了新对象,改变了变量的对象引用。
#### 二、可变对象
可变对象包括:列表、字典
其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。如下面的例子。
~~~
m=[5,9]
m+=[6]
~~~
列表m的每个元素均是对象的引用。对象的生成,涉及到对应机制,如整形对象分为大整数对象和小整数对象,生成机制不同,这里不作详细阐述。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/6fb4566f65208212b5284d86481ffd9c_968x177.png)
### 三、函数的参数传递
函数的参数传递,本质上传递的是引用。
### 拷贝
(1)没有限制条件的分片表达式(L[:])能够复制序列,但此法只能浅层复制。
(2)字典 copy 方法,D.copy() 能够复制字典,但此法只能浅层复制
(3)有些内置函数,例如 list,能够生成拷贝 list(L)
(4)copy 标准库模块能够生成完整拷贝:deepcopy,递归 copy
### 浅拷贝
浅拷贝由copy模块中的copy()函数实现,简单地说,copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的可变子对象。具体点说就是,**浅拷贝是指拷贝的只是原对象元素的引用,换句话说,浅拷贝产生的对象本身是新的,但是它的内容不是新的,只是对原子对象的一个引用。**
~~~
import copy
aList=[[1,2],3,4]
bList=copy.copy(aList)
print aList
print bList
print id(aList)
print id(bList)
aList[0][0]=5
print aList
print bList
~~~
由id(aList)不等于id(bList),表明浅拷贝产生的对象本身是新的,但是它的子对象(即,那个列表)是对原子对象的一个引用。**那么3,4两个元素呢?这就要讲讲python中的可变对象和不可变对象的引用了。**
但是有点需要特别提醒的,如果对象本身是不可变的,那么浅拷贝时也是引用。
见这个例子:
~~~
import copy
aList=[[1,2],3,4]
bList=copy.copy(aList)
print aList
print bList
print id(aList[1])
print id(bList[1])
aList[2]=5#变量的对象引用改变了而已
aList[0]=[0,1,1]#变量的对象引用改变了而已
print aList
print bList
~~~
总结,即**浅拷贝产生的对象本身是新的,但是它的内容不是新的,**只是对原**子对象**的一个**引用。**
### 深拷贝
浅拷贝由copy模块中的deepcopy()函数实现,简单地说,深拷贝 拷贝对象及其子对象。
一个例子展示引用、深拷贝与浅拷贝的不同。
~~~
import copy
aList=[[1,2],3,4]
bList=aList
cList=copy.copy(aList)
dList=copy.deepcopy(aList)
print aList
print bList
print cList
print dList
print id(aList)
print id(bList)
print id(cList)
print id(dList)
aList.append(5)
aList[0].append('hello')
print aList
print bList
print cList
print dList
~~~
其实我觉得记住这一点就行,**浅拷贝产生的对象本身是新的,但是它的内容不是新的,只是对原**子对象**的一个**引用**。关键是要理解python中引用的含义。**
';