zoukankan      html  css  js  c++  java
  • python06 深浅拷贝原理

    preface

    这里主要说深浅拷贝的原理。首先说说数字与字符串作为内存对象的重用,请看代码:

    a1=12345
    b1=12345
    a2=a1
    print(id(a1),id(b1),id(a2))
    

    打印出来的结果毫无疑问,ID值肯定是一样的。
    这就说明在python中,如果内存中有同样的对象(数字与字符串类型),那么我们在申明的时候是直接引用之前有的对象。

    浅拷贝

    浅拷贝,我们先看代码

    n1={'k1':'v1','k2':'v2','k3':{'he':'y1'}}
    n2 = copy.copy(n1)
    n3 = copy.deepcopy(n1)
    print(id(n1),id(n2))
    6754632 17766728
    print(id(n1['k3']),id(n2['k3']))
    6754504 6754504
    
    

    由打印结果可得,两个字典的ID值不一样了,但是呢,字典包含的value值还是一样的,正如前文说的一样,每个字典的字符串和数字型的元素ID还是一样的,所以说两个字典所引用的元素还是同一个的。请注意看第三个元素,第三个元素的value为字典类型,但是ID值仍是一样的。这就说明了浅拷贝的一个特性,浅拷贝拷贝的时候会把第一层元素一块copy过去,像字典这样有里面还有元素的,浅拷贝就不能把第一层字典里的value再复制过去了。所以我们看第二个print打印出来的结果是一样的。请看下面的一个例子:

    n1={'k1':'v1','k2':'v2','k3':{'he':'y1'}}
    n2 = copy.copy(n1)
    
    n1['k3']['he'] = 'n1'
    n2['k3']['he'] = 'n2'
    print(n1,'
    ',n2)
    {'k1': 'v1', 'k2': 'v2', 'k3': {'he': 'n2'}} 
    {'k1': 'v1', 'k2': 'v2', 'k3': {'he': 'n2'}}
    

    如上面的例子所示:由于浅拷贝是引用第一层元素,所以当我们修改n2的时候,也同时把n1修改了,因为他们的k3还是引用同一个值的。

    深拷贝

    先看代码:

    n1={'k1':'v1','k2':'v2','k3':{'he':'y1'}}
    n1['k3']['he'] = 'n1'
    n3['k3']['he'] = 'n3'
    print(n1,'
    ',n3)   
    {'k3': {'he': 'n1'}, 'k1': 'v1', 'k2': 'v2'} 
    {'k3': {'he': 'n3'}, 'k1': 'v1', 'k2': 'v2'}
    
    print(id(n1['k3']),'
    ',id(n3['k3']))
    6426824 
    12110664
    

    我们先看第一个print出来的结果,很显然,n3修改k3的值不会影响n1的k3的值,因为他们现在是两个不同的列表了,我们由第二个print出来的ID值可以看错来,两个k3的值不一样,所以谁也不影响谁,所以深拷贝就是能够把多层元素一块拷贝。

    深拷贝 VS 浅拷贝

    • 深拷贝:就是能够把多层元素一块拷贝,后续修改第二层(第三层或者第四层等等)元素的值的时候,不会影响其他深拷贝出来的对象。
    • 浅拷贝:只能复制第一层元素,后续修改第二层(第三层或者第四层等等)元素的值的时候,也会影响其他浅拷贝出来的对象。

    深浅拷贝的应用

    假设我们有一个模版,内容如下:

    info = {
        'cpu':[19],
        'mem':[87],
        'disk':[10],
    }
    

    这个时候我们需要在这模版上增加对应的数据,那么就必须要使用深拷贝了,代码如下:

    new_info = copy.deepcopy(info)
    new_info['cpu'].extend([56,12,32])
    

    打印出来的结果肯定不一样的。

  • 相关阅读:
    ibatis(sqlmap)中使用in语句的方法
    eclipse断点调试基础
    mysql+ef 连接版本问题
    控制台添加log4net
    IndexOf() LastIndexOf() Contains() StartsWith() EndsWith()方法比较
    mysql读写分离笔记
    EF 相关问题:给定关键词不在字典中
    Windows中使用Mysql-Proxy实现Mysql读写分离
    windows下的mysql配置文件在哪
    分组 根据某一列进行排序,根据shopid分组,用createTime排序,返回row_number()序号 select no =row_number() over (partition by shopId order by createTime desc), * from Goods_info
  • 原文地址:https://www.cnblogs.com/liaojiafa/p/6503242.html
Copyright © 2011-2022 走看看