Python的copy

深浅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。

原文地址:https://www.cnblogs.com/liunaixu/p/12451532.html