3.对象的分类:
容器对象:[1]
容器对象中包含的元素,是指向各个元素对象的引用。 (并不是元素对象本身。)
list、dict、set、tuple、str
序列对象:[2]
是有序集合,可以使用索引、切片功能。list、str、tuple
在Python中,
对象赋值实际上是对象的引用。[3]
创建一个对象,把它赋给另一个变量的时候,只拷贝这个对象的引用。(没拷贝这个对象)
1、浅拷贝:利用切片操作、工厂方法list方法拷贝
2、深拷贝:利用copy中的deepcopy方法进行拷贝
赋值引用'=':就是给将对象的引用赋值给变量,即给一段内存地址贴标签。
对于不可变对象,=、copy、deepcopy三者等价。[4]
针对可变对象 list,[:] 复制列表中的所有元素(浅拷贝)。
eek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
print(week[:])
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
list [:] 的浅拷贝 [5]
m = [1, 2, 3]
print('m', m, id(m))
n = m[:]
print('n', n, id(n))
n[1] = 4
print('m', m)
print('n', n)
2、浅拷贝 shallow copy:[6]
拷贝父对象的副本,但不会拷贝对象的内部的子对象。
构造一个新的对象并将原对象中的引用插入到新对象中,只拷贝了对象的地址,而不对对应地址所指向的具体内容进行拷贝,也就是依然使用原对象的引用。
浅拷贝只是拷贝了原始元素的引用(内存地址),拷贝对象的值是否会随着被拷贝对象变化,仅取决于原始元素是可变对象还是不可变对象。
[7]
3、深拷贝
完全拷贝了父对象及其子对象。
深拷贝复制的不只是原始元素的引用,而是整个原始元素对象。
因此,拷贝对象和被拷贝对象的值相互独立。
浅拷贝与深拷贝
list1 = [123, 456, 789, 213]
list2 = list1
list3 = list1[:]
print(list2) # [123, 456, 789, 213]
print(list3) # [123, 456, 789, 213]
list1.sort()
print(list2) # [123, 213, 456, 789]
print(list3) # [123, 456, 789, 213]
list1 = [[123, 456], [789, 213]]
list2 = list1
list3 = list1[:]
print(list2) # [[123, 456], [789, 213]]
print(list3) # [[123, 456], [789, 213]]
list1[0][0] = 111
print(list2) # [[111, 456], [789, 213]]
print(list3) # [[111, 456], [789, 213]]
一.浅拷贝
a 和 b 是一个独立的对象,他们的子对象还是引用同一对象。[8]
浅拷贝后,若改变可变对象元素的值,会同时影响浅拷贝对象;若改变不可变对象元素的值,不会响浅拷贝对象。
实现方式包括:工厂函数:list(), set()等、切片,copy模块的copy()方法。
#定义一个列表,第一个元素是可变类型
>>> A = [[1,2],'fei',90]
#浅拷贝
>>> B = copy.copy(A)
#对象地址是否相同
>>> A is B
False
#第一个元素地址是否相同
>>> A[0] is B[0]
True
#第二个元素地址是否相同
>>> A[1] is B[1]
True
#改变第一个可变类型的值,查看复制对象变化
>>> A[0][0] = 2
>>> A
[[2, 2], 'fei', 90]
#复制对象也跟着改变了
>>> B
[[2, 2], 'fei', 90]
#改变第二个不可变类型的值,查看复制对象变化
>>> A[1] = 'anne'
>>> A
[[2, 2], 'anne', 90]
#复制对象没有改变
>>> B
[[2, 2], 'fei', 90]
二.深拷贝
完全拷贝了父对象及其子对象[9],深拷贝得到的对象和原对象是完全独立的。
深拷贝,除了顶层拷贝,还对自对象也进行了拷贝。
经过深拷贝后,原始对象和拷贝对象所有的可变对象元素的地址都不相同。
实现方式:copy 模块的 deepcopy() 方法。
#深拷贝
>>> C = copy.deepcopy(A)
#对象地址是否相同
>>> A is C
False
#第一个元素地址是否相同
>>> A[0] is C[0]
False
#第二个元素地址是否相同
>>> A[1] is C[1]
True
#改变第一个元素,查看复制元素变化
>>> A[0][0] = 2
>>> A
[[2, 2], 'fei', 90]
#复制元素不变,对复制元素没影响
>>> C
[[1, 2], 'fei', 90]
#改变第二个元素,查看复制元素变化
>>> A[1] = 'Anne' >>> A
[[2, 2], 'Anne', 90]
#复制元素不变,对复制元素没影响
>>> C
[[1, 2], 'fei', 90]
三.赋值引用
a 和 b 都指向同一个对象。
#赋值引用
>>> A = [[1,2],'fei',90]
>>> D = A
#对象地址是否相同
>>> A is D
True
#第一个元素地址是否相同
>>> A[0] is D[0]
True
#第二个元素地址是否相同
>>> A[1] is D[1]
True
#改变A中第一个元素,查看是否影响D
>>> A[0][0] = 2
>>> A
[[2, 2], 'fei', 90]
#D中第一个元素也跟着改变
>>> D
[[2, 2], 'fei', 90]
#改变D中第二个元素,查看是否影响A
>>> D[1] = 'anne'
#A中第二个元素也改变了
>>> A
[[2, 2], 'anne', 90]
>>> D
[[2, 2], 'anne', 90]
[10]
参考
- ^容器对象 https://www.cnblogs.com/geaozhang/p/7111961.html
- ^序列对象和拆包 https://blog.csdn.net/weixin_44435602/article/details/110234494
- ^赋值引用、浅拷贝、深拷贝 https://www.cnblogs.com/geaozhang/p/7116025.html
- ^不可变对象,赋值、浅拷贝、深拷贝,三者等价: https://zhuanlan.zhihu.com/p/115242988
- ^切片、浅拷贝、深拷贝的区别: https://zhuanlan.zhihu.com/p/39566815
- ^浅拷贝、深拷贝: https://www.cnblogs.com/ybjourney/p/12951678.html
- ^浅拷贝、深拷贝 https://zhuanlan.zhihu.com/p/40449219
- ^浅拷贝与深拷贝(图) https://www.cnblogs.com/jiangfan95/p/11466398.html
- ^深拷贝 https://zhuanlan.zhihu.com/p/115242988
- ^图 https://www.cnblogs.com/jiangfan95/p/11466398.html