赋值、深拷贝和浅拷贝

1、赋值

对象之间赋值本质上是对象之间的引用传递,也就是多个对象指向同一个数据空间。当创建一个对象,把它赋值给另一个变量的时候,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。原始数据改变,被赋值的对象数据也会做相同的改变。

(1)列表之间的赋值

	a = [11,22]
	b = a
	print(id(a))    # 用来显示 a 指向的数据的内存地址
	print(id(b))    # 用来显示 b 指向的数据的内存地址

运行结果:
	1610957499464
	1610957499464

结论:
以上结果相同,说明了当给一个变量赋值时,其实就是将数据的引用复制了一份给了另外一个变量,这其实就是最简单的浅拷贝。

类似于 xx1 = xx2 这种类型的基本都是浅拷贝。

(2)字典之间的赋值

	c = {"name":"teacher"}
	d = c
	print(id(c))
	print(id(d))
	
	c["age"] = 20
	print(c)
	print(d)
	
运行结果:
	3127108004240
	3127108004240
	{'name': 'teacher', 'age': 20}
	{'name': 'teacher', 'age': 20}

2、浅拷贝

浅拷贝是对于一个对象的顶层拷贝,也就是只能拷贝最外面的一层。对于只有一层的数据可以完全拷贝;对于有多层数据的对象,只拷贝该对象的顶层,其余的只是把存放变量的地址值传给被赋值的对象,最后两个变量引用了同一份地址。通俗的理解是:拷贝了引用,并没有拷贝内容(指向了别人的内存地址,并没有建立一个新的内存地址)。

(1)对于只有一层数据的浅拷贝(完全拷贝,相当于深拷贝)

	import copy
	a = [1,2,3,4]
	b = copy.copy(a)
	print(a)
	print(b)
	print(id(a))
	print(id(b))
	a.append(9)
	print(a)
	print(b)
	print(id(a))
	print(id(b))
	
运行结果:
	[1, 2, 3, 4]
	[1, 2, 3, 4]
	2076501879368
	2076501879560
	[1, 2, 3, 4, 9]
	[1, 2, 3, 4]
	2076501879368
	2076501879560

(2)对于有两层数据的浅拷贝

1)查看id
	a = [11, 22]
	b = [33, 44]
	c = [a, b]
	print(id(a))
	print(id(b))
	print(id(c))
	print(id(c[0]))
	print(id(c[1]))
	
运行结果:
	2163059240008
	2163058363336
	2163059239880
	2163059240008
	2163058363336
2)举例
	import copy
	a = [11, 22]
	b = [33, 44]
	c = [a, b]
	d = copy.copy(c)
	print(id(a))
	print(id(b))
	print(id(c))
	print(id(d))
	print(id(d[0]))
	print(id(d[1]))
	a.append(11)
	print(c)
	print(d)
	
运行结果:
	2163059240008
	2163058363336
	2163059239880
	2163060779784
	2163059240008
	2163058363336
	[[11, 22, 11], [33, 44]]
	[[11, 22, 11], [33, 44]]

结论:
C对象的顶层数据就是[a,b],所以通过浅拷贝给D对象时D对象中也是[a,b]。
浅拷贝,只会复制最顶层的那个列表。

3、深拷贝

深拷贝是对于一个对象所有层次的拷贝(递归)。深拷贝是在内存中建立了一个新的内存地址,并另建了相同的数据。

(1)深拷贝举例

	import copy
	a = [11, 22]
	b = copy.deepcopy(a)   # 对a指向的列表进行深拷贝
	print(a)
	print(b)
	print(id(a))
	print(id(b))
	# 以上结果说明了通过deepcopy确实将a列表中所有的数据的引用拷贝了,而不是只拷贝了a指向的列表的引用
	a.append(33)
	print(a)
	print(b)
	
运行结果:
	[11, 22]
	[11, 22]
	2492948097608
	2492948097800
	[11, 22, 33]
	[11, 22]

(2)进一步理解深拷贝

	import copy
	a = [11, 22]
	b = [33, 44]
	c = [a, b]
	d = copy.deepcopy(c)
	print(id(a))
	print(id(b))
	print(id(c))
	print(id(c[0]))
	print(id(c[1]))
	print(id(d))
	print(id(d[0]))
	print(id(d[1]))
	c[0].append(55)
	print(c)
	print(d)
	
运行结果:
	1784636648008
	1784636648200
	1784635290184
	1784636648008
	1784636648200
	1784635290312
	1784635290376
	1784636649224
	[[11, 22, 55], [33, 44]]
	[[11, 22], [33, 44]]

4、浅拷贝和深拷贝对不可变类型的拷贝

copy.copy对于可变类型,会进行浅拷贝。
copy.copy和copy.deepcopy对于不可变类型没有意义,全部等价于对象之间的赋值操作,即为引用的传递。

(1)浅拷贝对可变类型的copy

	import copy
	a = (11, 22, 33)
	b = copy.copy(a)
	print(id(a))
	print(id(b))
	
运行结果:
	2130815156424
	2130815156424

(2)深拷贝对可变类型的copy

	import copy
	a = (11, 22, 33)
	b = copy.deepcopy(a)
	print(id(a))
	print(id(b))
	
运行结果:
	2341555192456
	2341555192456

总结

(1)不可变对象类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。
(2)对于可变对象深浅拷贝:

  • =(浅拷贝)浅拷贝:值相等,地址相等
  • copy(浅拷贝):值相等,地址不相等
  • deepcopy(深拷贝):值相等,地址不相等

(3)深浅拷贝的作用:

  • 减少内存的使用。
  • 以后在做数据的清洗、修改或者入库的时候,对原数据进行复制一- 份,以防数据修改之后,找不到原数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值