拷贝大家都比较熟悉,就是复制,其实又和传统的复制有一定的区别
一、赋值
赋值就是把一个对象的引用(在内存中的存储地址即存储对象的内存地址)和变量进行关联起来。对象的地址可通过函数id查询及id(obj),如a=b,其实就是把a的内存地址和变量b关联起来。
a=['a',3,'c','b',[2,'b']]
b=a #a的内存地址与变量b关联
print(a,b)
print(id(a),id(b))
"""a和b的地址是一样的,所以a和b两个变量中任何一个发生改变另外一个也会跟着改变因为他们俩的地址是一样的"""
a[1]='d'
print(a,b)
b[4][0]='a'
print(a,b)
a.append('e')
print(a,b)
print(id(a),id(b))
"""小结:1、一旦对象生成后那么它的存储地址就会固定了,所以再怎么改变变量的值,它的存储地址不会改变
2、经过赋值后两个变量的地址一样,类似于指针,所以改变其中任何一个另外一个会跟着改变"""
执行结果:
['a', 3, 'c', 'b', [2, 'b']] ['a', 3, 'c', 'b', [2, 'b']]
1575497342144 1575497342144
['a', 'd', 'c', 'b', [2, 'b']] ['a', 'd', 'c', 'b', [2, 'b']]
['a', 'd', 'c', 'b', ['a', 'b']] ['a', 'd', 'c', 'b', ['a', 'b']]
['a', 'd', 'c', 'b', ['a', 'b'], 'e'] ['a', 'd', 'c', 'b', ['a', 'b'], 'e']
1575497342144 1575497342144
二、浅拷贝和深拷贝
浅拷贝(copy):拷贝父对象,不会拷贝对象内部的子对象,b=a.copy(),并且浅拷贝两个变量的存储地址不一样,但他们的子变量的地址是一样的,这也正是浅拷贝,看列子
a=['a',3,'c','b',[2,'b']]
b=a.copy() #会把a的值给b,两个变量地址不同,但他们的子对象地址是相同的即a[0]和b[0],a[1]和b[1]....
print(a,b) #['a', 3, 'c', 'b', [2, 'b']] ['a', 3, 'c', 'b', [2, 'b']]
print(id(a),id(b)) #2552750447808 2552749752512
print(id(a[4]),id(b[4])) #2552749753472 2552749753472
print(id(a[1]),id(b[1])) #140723581785824 140723581785824
a[2]='B' #这个只是改变变量a,对变量b没有影响
print(a,b) #['a', 3, 'B', 'b', [2, 'b']] ['a', 3, 'c', 'b', [2, 'b']]
a[4][1]='S' #正是因为a[4]和b[4]地址相同,我们改变a[4][1]而变量b会跟着改变
print(a,b) #['a', 3, 'B', 'b', [2, 'S']] ['a', 3, 'c', 'b', [2, 'S']]
深拷贝(deepcopy):通过copy模块的deepcopy,完全拷贝了父对象和子对象,父变量和子变量的地址均不相同
import copy
a=['a',3,'c','b',[2,'b']]
b=copy.deepcopy(a) #会把a的值给b,两个变量地址不同,他们的子对象地址也是不相同的即a[0]和b[0],a[1]和b[1]....
print(a,b) #['a', 3, 'c', 'b', [2, 'b']] ['a', 3, 'c', 'b', [2, 'b']]
print(id(a),id(b)) #1813443893184 1813443788480
print(id(a[4]),id(b[4])) #1813444051520 1813444046656
print(id(a[1]),id(b[1])) #140723581785824 140723581785824
a[2]='B' #这个只是改变变量a,对变量b没有影响
print(a,b) #['a', 3, 'B', 'b', [2, 'b']] ['a', 3, 'c', 'b', [2, 'b']]
a[4][1]='S' #因为a和b的父变量和子变量地址均不同,所以我们改变a而变量b不会跟着改变
print(a,b) #['a', 3, 'B', 'b', [2, 'S']] ['a', 3, 'c', 'b', [2, 'b']]
小结:1、赋值把对象和对象的地址都赋值过去了
2、拷贝只是把对象复制过去,而对象会产生新的地址
3、只有当存储地址一样了,只要改变其中一个另外一个也会跟着改变