深浅copy
浅copy():如果原列表都是不可变类型,使用浅copy即可。(浅copy:对列表第一层地址拷贝)
深copy():如果愿列表有可变类型存在(如列表里嵌套一个列表),使用深copy。(深copy:对列表的第一层和第二层拷贝)
实战:
需求:定义一个列表
# 定义一个列表 l1 = ["egon", 'lxx', [1, 2]]
# 索引 0 1 2
如图所示:
在栈区中开辟:变量名l1关联列表的内存地址0xffff0030,共同指向堆区
在堆区中开辟:索引是0 的内存地址0xffff1111它指向的值为‘egon’,
索引是1 的内存地址0xffff2222它指向的值为‘lxx’,
索引是2 的内存地址0xffff3333它指向的是子列表[1,2]的内存地址。
子列表在堆区中又开辟:
索引是0 的内存地址0xffff4441它指向的值为1
索引是0 的内存地址0xffff5551它指向的值为2
# 定义一个列表
l1 = ["egon", 'lxx', [1, 2]]
print(l1)
print(id(l1)) # 31342344
# l1 赋给 l2
l2 = l1
print(l2)
print(id(l2)) # 31342344
在栈中开辟:变量名l2关联列表的内存地址0xffff0030,指向l1指向的堆区。
# l1改变了,l2也变了,互相操作则互相影响。
l1[0] = 'lsj'
print(l1,l2) # ['lsj', 'lxx', [1, 2]] ['lsj', 'lxx', [1, 2]]
print(id(l1),id(l2)) # 31276808 31276808
需求:
如果我想创建一个列表l3,复制列表l1的内容,使其修改操作独立分开,当互相操作时互不影响,该怎么办?
提炼需求:1、拷贝一下列表,产生新的需求。
2、想让两个列表完全独立开(针对改操作)。(读的操作有意义么?--没有)
这就用到了copy:我们先验证浅copy()行不行?
# 浅copy(),先定义一个列表
l1 = ["egon", 'lxx', [1, 2]]
print(l1) # ['egon', 'lxx', [1, 2]]
print(id(l1)) # 34815880
# 进行copy()
l3 = l1.copy()
print(l3) # ['egon', 'lxx', [1, 2]] 证明l3的值和l1的值相同
print(id(l1),id(l3)) # 34815880 34815944
print(id(l1[0]),id(l1[1]),id(l1[2])) # 34865312 37715448 34881480
print(id(l3[0]),id(l3[1]),id(l3[2])) # 34865312 37715448 34881480
# 拷贝完后修改l1的值查看l3的值变化没有?
l1[0] = 'EGON' # 针对不可变类型修改其值
l1[1] = 'LXX'
# l1[2] = 123
# print(l1,l3) # ['EGON', 'LXX', 123] ['egon', 'lxx', [1, 2]] 证明l1变了,l3没有变
l1[2][0] = 111 # 针对可变类型修改其值
l1[2][1] = 222
print(l1,l3) # 但是当子列表值修改后['EGON', 'LXX', [111, 222]] ['egon', 'lxx', [111, 222]] l1,l3的值都变了
解析:当l3 = l1.copy()证明l1的值拷贝到了l3
在栈区中开辟:变量名l3关联列表的内存地址0xffff6666,共同指向堆区
在堆区中开辟:索引是0 的内存地址0xffff1111它指向的值为‘egon’,
索引是1 的内存地址0xffff2222它指向的值为‘lxx’,
索引是2 的内存地址0xffff3333它指向的是子列表[1,2]的内存地址。
子列表在堆区中又开辟:
索引是0 的内存地址0xffff4441它指向的值为1
索引是1 的内存地址0xffff5551它指向的值为2
综上所述:浅copy:把列表第一层内存地址,不加区分(区分的是可变类型和不可变类型)完全拷贝到新的列表。
浅copy():如果原列表都是不可变类型,使用浅copy完全没问题。(浅copy:对列表第一层地址拷贝)
深copy():如果愿列表有可变类型存在(如列表),就会出问题。(深copy:对列表的第一层和第二层拷贝)
深copy:我要对列表里的数据类型区分,那就要用到deepcopy()
import copy
# 深copy(),先定义一个列表
l1 = ["egon", 'lxx', [1, 2]]
l4 = copy.deepcopy(l1)
print(id(l1),id(l4)) # 39260552 39261832
# 深copy对可变类型地址拷贝一份。
# 类型:不可变 不可变 可变
print(id(l1[0]),id(l1[1]),id(l1[2])) # 34668704 35421688 39063752
print(id(l4[0]),id(l4[1]),id(l4[2])) # 34668704 35421688 39065160
# 查看可变类型里的id地址
print(id(l1[2][0]),id(l1[2][1])) # 492265696 492265728
print(id(l4[2][0]),id(l4[2][1])) # 492265696 492265728
针对不可变类型就会使用原来的地址,针对不可变类型就会造一个新的地址
l1[0] = 'EGON'
l1[1] = 'LXX'
l1[2][0] = 111 # 原内存地址不变,创建一个新的值
l1[2][1] = 222 # 原内存地址不变,创建一个新的值
print(l1,l4) # ['EGON', 'LXX', [111, 222]] ['egon', 'lxx', [1, 2]] # copy的列表值未变
结论:
如果我想拷贝一个新的列表,复制前一个列表的内容,要使其修改操作独立分开,要是用深copy。