Python中的深拷贝与浅拷贝
一.可变与不可变
python数据类型
数据类型 | 特征 |
---|---|
列表 | 有序、可变 |
元组 | 有序、不可变 |
字符串 | 无序、可变 |
字典 | 无序、可变 |
集合 | 有序、不可变 |
基于值的内存管理方式
对列表进行添加元素的方法
向列表中添加新元素有三种常用的方法,分别为:
L=L+[i], L.append(i), L+=[i]
下面我们来总结一下这三种方法的差别:
(1) L=L+[i]在每一次执行时都会将原列表复制一次,L 指向新列表,并 在新列表中加入新元素。
(2) L.append(i)只是将新元素直接添加到原列表中,不会产生新列表。
(3) L+=[i]的执行效果和 L.append(i)类似,也是在原列表中直接添加元 素,不会复制原列表。 Python 中可以通过 id()函数来查看列表存储的地址,如果语句执行前后列 表的地址不同,那么就说明原列表被复制,此时的 L 指向新列表的地址。反 之,则列表没有被复制,L 仍指向原列表
不管是可变还是不可变的序列类型:
(1)分片必定产生新的序列
(2)“+”号在等号右边,必定产生新的序列,然后将新的序列地址赋予给等号左边的变量
列表方法list.copy() ---- 浅拷贝
s = [1,2,3]
b = s.copy()
s[0] = 6
print(s,b)
输出结果:
[6,2,3] [1,2,3]
copy模块中的copy()、deepcopy()函数
copy.copy() 浅拷贝
copy.deepcopy() 深拷贝
import copy
a=[1,2,[3,4],{'a':1}] # 原始对象
b=a # 赋值,传对象的引用
c=copy.copy(a) # 对象拷贝,浅拷贝
d=copy.deepcopy(a) # 对象拷贝,深拷贝
e=a[:] # 能复制序列,浅拷贝
a.append('add1') # 修改对象a
a[2].append('add2') # 修改对象a中的[3,4]数组对象
a[3]='666'
print('a:',a)
print('b:',b)
print('c:',c)
print('d:',d)
print('e:',e)
输出结果
a: [1, 2, [3, 4, 'add2'], '666', 'add1']
b: [1, 2, [3, 4, 'add2'], '666', 'add1']
c: [1, 2, [3, 4, 'add2'], {'a': 1}]
d: [1, 2, [3, 4], {'a': 1}]
e: [1, 2, [3, 4, 'add2'], {'a': 1}]
二.Numpy中的深拷贝与浅拷贝
共享内存地址的两个变量
共享内存地址的两个变量当其中一个变量的值改变时,另一个变量的值也随之改变。此时,变量间的拷贝是浅拷贝
和Python的列表序列不同,ndarray对象通过下标范围获取的新的数组是原始数据的一个视图(
view
),它与原始数据共享一块数据空间。
ndarray.view() ---- 浅拷贝
共享视图’view’的两个变量当其中一个变量的值改变时,另一个变量的值也随之改变。此时,变量间的拷贝是浅拷贝
np.copy() ---- 深拷贝
通过深拷贝
得到的变量互不干扰,其中一个变量的值改变时,不影响其他变量的值。