zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    C#中的委托(转)
    面试总结
    int, Int32.Parse和Convert.ToInt32的不同之处(分享)
    数据结构与算法基础学习(一)
    SVN服务器搭建和使用(二)
    WCF学习笔记(第一天,1.WCF概述)
    在此计算机中仅有部分visual studio2010产品已升级到SP1,只有全部升级,产品才能正常运行解决办法
    FormsAuthentication使用指南
    Why do I get the error "The target GatherAllFilesToPublish does not exist"?
    非彼拉且数列的实现
  • 原文地址:https://www.cnblogs.com/liunaixu/p/12451532.html
Copyright © 2011-2022 走看看