• 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。

  • 相关阅读:
    Leetcode Spiral Matrix
    Leetcode Sqrt(x)
    Leetcode Pow(x,n)
    Leetcode Rotate Image
    Leetcode Multiply Strings
    Leetcode Length of Last Word
    Topcoder SRM 626 DIV2 SumOfPower
    Topcoder SRM 626 DIV2 FixedDiceGameDiv2
    Leetcode Largest Rectangle in Histogram
    Leetcode Set Matrix Zeroes
  • 原文地址:https://www.cnblogs.com/liunaixu/p/12451532.html
Copyright © 2020-2023  润新知