精华内容
下载资源
问答
  • deepcopy
    2022-07-26 18:19:29

    关于python deepcopy内存问题

    这个问题主要发生在我使用numpy.load加载多个大型数据的时候,原本计划是加载一个数据,然后从其中使用deepcopy取出一部分数据,再使用del函数去进行释放空间,再加载下一个数据。但是在实际使用当中,deepcopy并没有使新数据划出空间,反而使得取出来的数据与原数据指向同一内存空间。

    a = np.load(“a.npy”)
    c=[]
    max_size=1000
    len= len(a)
    perm_indices = np.random.permutation(len)[:(max_size)]
    for j in perm_indices:
    	c.append(copy.deepcopy(a[j]))
    

    这就导致我在加载数据的时候内存不断增长直至爆炸!
    所以我进行了以下的测试,首先申请了一个长度为200w的数组a,然后再重新申请一个长度和数值与一模一样的数组b,再使用deepcopy函数给数组b附上数组a的值

    import numpy as np
    import os
    import psutil
    import gc
    import copy
    import sys
    def listcopy(x):
        a = len(x)
        b = [i for i in range(a)]
        for i in range(a):
            b[i] = copy.deepcopy(x[i])
        return b
    print('A:%.2f MB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024))
    list1=[ i for i in range(2000000)]
    print('B:%.2f MB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024))
    list2=listcopy(list1)
    print('C:%.2f MB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024))
    del list1
    gc.collect()
    print('D:%.2f MB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024))
    

    他的输出如下:

    A:38.52 MB
    B:116.77 MB
    C:131.18 MB
    D:115.87 MB
    

    如果我将listcopy()部分代码注释掉

    def listcopy(x):
        a = len(x)
        b = [i for i in range(a)]
        #for i in range(a):
        #   b[i] = copy.deepcopy(x[i])
        return b
    

    这就表示b是完全新申请的空间与a无关,这时候输出是

    A:38.40 MB
    B:115.70 MB
    C:193.09 MB
    D:116.06 MB
    

    显然虽然值相同,但是比没有使用deepcopy所要占的内存要大一些,当然,我们还是要尝试一下直接使用deepcopy拷贝,也就是将list2=listcopy(list1)替换为list2=copy.deepcopy(list1)这时候输出为:

    A:38.38 MB
    B:116.48 MB
    C:130.91 MB
    D:115.63 MB
    

    和分部拷贝差不多,但是如果我们将listcopy()函数中的复制的长度减少,也就是如下改变:

    def listcopy(x):
        a = len(x)
        b = [i for i in range(a)]
        for i in range(int(a/2)):
            b[i] = copy.deepcopy(x[i])
        return b
    

    他的输出将会是

    A:38.51 MB
    B:115.75 MB
    C:163.00 MB
    D:116.72 MB
    

    我们将会看到相较于没有进行拷贝和完全拷贝,这个内存占用大于完全拷贝,小于不进行拷贝。在之后测试之中我试过将复制长度再缩小一倍,这个内存占用还会曾大。这说明deepcopy虽然是深度拷贝,但是python似乎还是将一些值指向了同样的内存。这就导致释放原数据的时候并不能完全释放。
    但是我还是找到了一个不算是解决方法的方法就是在拷贝的时候直接乘1,也就是将listcopy()修改如下:

    def listcopy(x):
        a = len(x)
        b = [i for i in range(a)]
        for i in range(a):
            b[i] = x[i]*1
        return b
    

    这时候输出就正常了

    A:38.26 MB
    B:115.80 MB
    C:192.86 MB
    D:115.85 MB
    
    更多相关内容
  • deepcopy.js 深度复制数据安装npm $ npm install deepcopy用法node.jsJavaScript const deepcopy = require ( 'deepcopy' ) ;打字稿import * as deepcopy from 'deepcopy' ;浏览器< script src =" deepcopy.min....
  • 深度复制DeepCopy可帮助您创建对象的深层副本(克隆)。 它旨在处理关联图中的循环。目录如何? 使用Composer安装: composer require myclabs/deep-copy 简单使用: use DeepCopy \ DeepCopy ;$ copier = new ...
  • 以下是个人对Python深浅拷贝的通俗解释,易于绕开复杂的Python数据结构存储来进行理解! 高级语言中变量是对内存及其地址的抽象,Python的一切变量都是对象。 变量的存储采用了引用语义的方式,存储的只是一个变量...
  • deepcopy() 是真正意义上的复制,即重新开辟一片空间,经常说的复制实际上就是 deepcopy,深层复制之后的对象不受原对象的影响,无论原对象发生什么修改,深层复制的对象都不会发生改变。 >>> import c
  • Python学习过程中会遇到许多问题,最近对copy和deepcopy略感困惑,下面对其进行解答,需要的朋友可以参考。
  • 最近需要用到比较两个对象属性的变化,其中一个是oldObj,另外一个是newObj,oldObj是newObj的前一个状态,所以需要在newObj的某个状态时,复制一个一样的对象,由于JAVA不支持深层拷贝,因此专门写了一个方法
  • 主要介绍了Python-copy()与deepcopy()区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 接触python有一段时间了,一直没有系统的学习过,也对copy,deepcoy傻傻的分不清,故抽出时间来理一下。 下面这篇文章主要给大家介绍了关于python中copy()与deepcopy()的区别的相关资料,需要的朋友可以参考下
  • python list的deepcopy过慢(csdn)————程序
  • python list的deepcopy过慢

    千次阅读 2021-11-21 16:12:43
    程序跑的很慢,使用bottleneck一分析发现问题出在deepcopy上。 因为程序是需要对列表进行操作,而我的程序逻辑是要求必须对列表进行深拷贝,于是没有办法绕过。 只能想办法加速这个深层拷贝。 我想到四种方法 第一种...

    程序跑的很慢,使用bottleneck一分析发现问题出在deepcopy上。
    因为程序是需要对列表进行操作,而我的程序逻辑是要求必须对列表进行深拷贝,于是没有办法绕过。
    只能想办法加速这个深层拷贝。
    我想到四种方法
    第一种:deepcopy,这没得啥说的。是baseline.

    ##直接deepcopy
    def method1(origin_list, step):
        for each in range(step):
            l = copy.deepcopy(origin_list)
        return l
    

    第二种:使用numpy,先转为numpy对象,然后再tolist

    ##转换为numpy, 然后再tolist()
    def method2(origin_list, step):
        for each in range(step):
            l = np.array(origin_list).tolist()
        assert type(l) == type(origin_list)
        return l
    

    第三种:使用pickle,先pickle.dump,再pickle.load

    ##使用pickle
    def method3(origin_list, step):
        for each in range(step):
            l = pickle.loads(pickle.dumps(origin_list))
        assert type(l)== type(origin_list)
        return l
    

    第四种,使用ujson,也是先usjon.dump,在ujson.load。

    ##使用ujson
    def method4(origin_list, step):
        for each in range(step):
            l = ujson.loads(ujson.dumps(origin_list))
        assert type(l)== type(origin_list)
        return l
    

    分别拷贝10000次,测试如下:

    __author__ = 'dk'
    import numpy as np
    import copy
    import time
    import pickle
    import ujson
    
    ##直接deepcopy
    def method1(origin_list, step):
        for each in range(step):
            l = copy.deepcopy(origin_list)
        return l
    
    ##转换为numpy, 然后再tolist()
    def method2(origin_list, step):
        for each in range(step):
            l = np.array(origin_list).tolist()
        assert type(l) == type(origin_list)
        return l
    
    ##使用pickle
    def method3(origin_list, step):
        for each in range(step):
            l = pickle.loads(pickle.dumps(origin_list))
        assert type(l)== type(origin_list)
        return l
    
    ##使用ujson
    def method4(origin_list, step):
        for each in range(step):
            l = ujson.loads(ujson.dumps(origin_list))
        assert type(l)== type(origin_list)
        return l
    if __name__ == '__main__':
        origin_list = [[i for  i in range(30)] for i in range(30)]
        step = 10000
    
        t = time.time()
        method1(origin_list,step)
        e = time.time()
        print(e-t)
    
        t = time.time()
        method2(origin_list,step)
        e = time.time()
        print(e-t)
    
        t = time.time()
        method3(origin_list,step)
        e = time.time()
        print(e-t)
    
        t = time.time()
        method4(origin_list,step)
        e = time.time()
        print(e-t)
    

    输出结果:

    方法耗时
    deepcopy6.8964385986328125
    numpy1.1347527503967285
    pickle0.5621602535247803
    ujson0.7545688152313232

    所以,如果list深层次拷贝绕不过去,就用pickle吧!
    哎~·

    展开全文
  • python学习 - copy模块的浅复制(copy)与深复制(deepcopy)简介copy.copy()详解copy.deep 简介 在使用列表或者字典进行传递参数的时候,可能会遇到函数改变了列表的值,但是不希望印象原来列表中的值,所以,...

    python学习 - copy模块的浅复制(copy)与深复制(deepcopy)

    简介

    在使用列表或者字典进行传递参数的时候,可能会遇到函数改变了列表的值,但是不希望印象原来列表中的值,所以,python提供了copy模块,其中包含copy()和deepcopy()两函数,顾名思义copy()指的就是浅复制,deepcopy()指的就是深复制。

    copy.copy()详解

    copy.copy()主要是用来复制一维列表或者一维元组,即 像[‘A’,‘B’,‘C’,‘D’]这种,如果列表中再套列表,比如这种[‘A’,‘B’,[‘d’,‘e’,‘f’],‘C’] 就不能进行复制更改。下面来做一个简单的测试。

    import copy
    lis_A = ['A','B','C','D']
    lis_B = ['A','B',['d','e','f'],'C']
    
    # 使用copy.copy()复制lis_A
    copy_A = copy.copy(lis_A)
    print('lis_A的值',  lis_A)
    print('copy_A的值', copy_A)
    
    # 打印出lis_A和copy_A的ID值
    print('lis_A的ID值',  id(lis_A))
    print('copy_A的ID值', id(copy_A))
    
    

    输出结果是:

    lis_A的值 ['A', 'B', 'C', 'D']
    copy_A的值 ['A', 'B', 'C', 'D']
    lis_A的ID值 1347357010368
    copy_A的ID值 1347357613888
    

    这里可以看出。copy_A的值与lis_A的值是一样的,但是它们的ID值是不一样的,说明copy_A指向了一个独立的列表。那么改变copy_A的值是不会去影响lis_A的列表的值,可以做试验:

    从上面可以看出,我改变了copy_A中的 ‘B’ 的值,但是并没有影响到lis_A中的值。

    使用copy()复制嵌套列表会是什么结果呢?

    lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
    # 使用copy_B复制 lis_B
    copy_B = copy.copy(lis_B)
    
    # 分别打印lis_B和copy_B的值
    print('lis_B的值',  lis_B)
    print('copy_B的值', copy_B)
    
    # 打印出lis_B和copy_B的ID值
    print('lis_B的ID值',  id(lis_B))
    print('copy_B的ID值', id(copy_B))
    

    输出的结果是:

    lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
    copy_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
    lis_B的ID值 2116281195712
    copy_B的ID值 2116321275968
    

    咦,也复制出来了呀,怎么回事?别急,接着看,我们 改变一下copy_B中的 B 的值试试。

    lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
    # 使用copy_B复制 lis_B
    copy_B = copy.copy(lis_B)
    # 改变copy_B中的 B 的值
    copy_B[1] = '改变B'
    
    # 分别打印lis_B和copy_B的值
    print('lis_B的值',  lis_B)
    print('copy_B的值', copy_B)
    
    # 打印出lis_B和copy_B的ID值
    print('lis_B的ID值',  id(lis_B))
    print('copy_B的ID值', id(copy_B))
    

    输出结果:

    lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
    copy_B的值 ['A', '改变B', ['d', 'e', 'f'], 'C']
    lis_B的ID值 2258614705408
    copy_B的ID值 2258654720640
    

    从上可以看出,copy_B中B的值已经被改变了,怎么回事?要翻车了吗?
    我们再改变一下copy_B中的的整个列表试试?

    lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
    # 使用copy_B复制 lis_B
    copy_B = copy.copy(lis_B)
    
    # # 改变copy_B中的 B 的值
    # copy_B[1] = '改变B'
    
    # 改变lis_B中嵌套的列表 试试?
    copy_B[2] = ['1', '2', '3']
    
    # 分别打印lis_B和copy_B的值
    print('lis_B的值', lis_B)
    print('copy_B的值', copy_B)
    
    # 打印出lis_B和copy_B的ID值
    print('lis_B的ID值', id(lis_B))
    print('copy_B的ID值', id(copy_B))
    
    

    输出的结果是:

    lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
    copy_B的值 ['A', 'B', ['1', '2', '3'], 'C']
    lis_B的ID值 1860576959872
    copy_B的ID值 1860618301312
    

    copy_B的列表也变了。在改变一下copy_B嵌套列表 [‘1’, ‘2’, ‘3’] 中的‘2’的值呢?

    lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
    # 使用copy_B复制 lis_B
    copy_B = copy.copy(lis_B)
    
    # # 改变copy_B中的 B 的值
    # copy_B[1] = '改变B'
    
    # 改变lis_B中嵌套的列表 试试?
    copy_B[2] = ['1', '2', '3']
    # 改变lis_B中嵌套的列表中的值 试试?
    copy_B[2][1] = '改变2'
    
    # 分别打印lis_B和copy_B的值
    print('lis_B的值', lis_B)
    print('copy_B的值', copy_B)
    
    # 打印出lis_B和copy_B的ID值
    print('lis_B的ID值', id(lis_B))
    print('copy_B的ID值', id(copy_B))
    
    

    输出结果:

    lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
    copy_B的值 ['A', 'B', ['1', '改变2', '3'], 'C']
    lis_B的ID值 2763457256768
    copy_B的ID值 2763497140352
    

    啊,‘2’也改变了,没有影响lis_B的值,怎么回事啊,翻车了吗?
    我们直接改变复制出来的copy_B的嵌套列表的值,不先改变嵌套列表试试呢。

    lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
    # 使用copy_B复制 lis_B
    copy_B = copy.copy(lis_B)
    
    # # 改变copy_B中的 B 的值
    # copy_B[1] = '改变B'
    
    # # 改变lis_B中嵌套的列表 试试?
    # copy_B[2] = ['1', '2', '3']
    # # 改变lis_B中嵌套的列表中的值 试试?
    # copy_B[2][1] = '改变2'
    # 直接改变copy_B的值,将上两步注释掉,此时copy_B = lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
    copy_B[2][1] = '改变2'  # 改变2 是改变 ['A', 'B', ['d', 'e', 'f'], 'C'] 中的 e
    
    # 分别打印lis_B和copy_B的值
    print('lis_B的值', lis_B)
    print('copy_B的值', copy_B)
    
    # 打印出lis_B和copy_B的ID值
    print('lis_B的ID值', id(lis_B))
    print('copy_B的ID值', id(copy_B))
    

    输出结果:

    lis_B的值 ['A', 'B', ['d', '改变2', 'f'], 'C']
    copy_B的值 ['A', 'B', ['d', '改变2', 'f'], 'C']
    lis_B的ID值 2342836779328
    copy_B的ID值 2342878850496
    

    神奇的一幕发生了,改变的是copy_B中的e的值,但是lis_B中e的值也发生了改变。

    看懂了吗?这就是使用copy.copy()复制嵌套列表的弊端,表面看复制了lis_B[但是有没有完全复制 lis_B ,这种情况就要使用deepcopy()来进行复制。

    但是,为什么之前的情况.为什么能将嵌套列表[‘d’, ‘e’, ‘f’]改为[‘1’, ‘2’, ‘3’],再将[‘1’, ‘2’, ‘3’]的 ‘2’ 变为 ‘改变2’呢。
    (1)为什么能将 [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’]?
    简单理解,在整体改变[‘d’, ‘e’, ‘f’] 可以把他看做为一个整体,由X来代替,[‘1’, ‘2’, ‘3’]由Y来代替。所以此时的变更相当于把[‘A’, ‘B’, X, ‘C’] 变更为 [‘A’, ‘B’, Y, ‘C’]。实际上变更的还是一维列表。copy.copy()是可以复制一维列表的。
    (2)为什么 copy_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’],再去变[‘1’, ‘2’, ‘3’]中的‘2’时,不会影响lis_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’]?
    原因是第一步将 copy_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’] 此时已经产生了一个新的列表 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’] ,与列表 lis_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 是两个完全不相同的两个列表。自然不回影响。

    如果说有个列表 lis_C = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], [‘x’,‘y’]],先变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], [‘x’,‘y’]],再去改变 'x’变会对源列表产生影响

    # 定义一个lis_C
    lis_C = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
    
    # 复制一个 copy_C
    copy_C = copy.copy(lis_C)
    # copy_C = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']] 变为 ['A', 'B', ['1', '2', '3'], ['x', 'y']]
    copy_C[2] = ['1', '2', '3']
    
    # 在来改变 ['A', 'B', ['1', '2', '3'], ['x', 'y']] 中 'x'的值
    copy_C[3][0] = '改变x'
    
    # 分别打印copy_C和copy_C的值
    print('lis_C的值', lis_C)
    print('copy_C的值', copy_C)
    
    # 打印出lis_C和copy_C的ID值
    print('lis_C的ID值', id(lis_C))
    print('copy_C的ID值', id(copy_C))
    

    输出结果:

    lis_C的值 ['A', 'B', ['d', 'e', 'f'], ['改变x', 'y']]
    copy_C的值 ['A', 'B', ['1', '2', '3'], ['改变x', 'y']]
    lis_C的ID值 2790729135616
    copy_C的ID值 2790729135424
    

    从可以看出,copy_C 中[‘d’, ‘e’, ‘f’] 变成[ ‘1’, ‘2’, ‘3’]时,并不影响lis_C,在 将 [‘x’, ‘y’] 变为 [‘改变x’, ‘y’]时就会印象lis_C

    copy.deepcopy()详解

    上面说到,在使用copy.copy()复制嵌套的二维列表[‘A’, ‘B’, [‘d’, ‘e’, ‘f’], [‘x’, ‘y’]],然后改变嵌套列表中的值是,会影响到源列表的值,那么使用copy.deepcopy()是否会影响源列表呢?

    import copy
    # 定义一个lis_D
    lis_D = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
    
    # 使用deepcopy()复制一个 copy_C
    copy_D = copy.deepcopy(lis_D)
    # 直接改变 copy_D 中嵌套列表 ['d', 'e', 'f'] 中的值d
    copy_D[2][0] = '改变d'
    
    # 分别打印copy_D和copy_D的值
    print('lis_D的值', lis_D)
    print('copy_D的值', copy_D)
    
    # 打印出lis_D和copy_D的ID值
    print('lis_D的ID值', id(lis_D))
    print('copy_D的ID值', id(copy_D))
    

    输出结果:

    lis_D的值 ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
    copy_D的值 ['A', 'B', ['改变d', 'e', 'f'], ['x', 'y']]
    lis_D的ID值 2335362856512
    copy_D的ID值 2335362856320
    

    从上述结果可以很明显的看出,使用deepcopy()复制列表lis_之后,直接改变二维列表中的值 d,不会影响到源列表lis_D

    展开全文
  • copy()与deepcopy()之间的主要区别是python对数据的存储方式。python2中,需要import copy模块。python3中,直接可以使用copy()方法,但deepcopy()还是需要导入copy模块 >首先直接上结论: —–深复制,...

    copy()与deepcopy()之间的主要区别是python对数据的存储方式。python2中,需要import copy模块。python3中,直接可以使用copy()方法,但deepcopy()还是需要导入copy模块

    >首先直接上结论:

    —–深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。 

    —–而等于赋值,并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。

    —–而浅复制要分两种情况进行讨论:

    1)当浅复制的值是不可变对象(数值,字符串,元组)和“等于赋值”的情况一样,对象的id值与浅复制原来的值相同。

    2)当浅复制的值是可变对象(列表和元组)时会产生一个“不是那么独立的对象”存在。有两种情况:

    第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

    第二种情况复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表),如果不改变其中复杂子对象浅复制的值改变并不会影响原来的值。 但是改变原来的值 中的复杂子对象的值  会影响浅复制的值

    对于简单的 object,例如不可变对象(数值,字符串,元组),用 shallow copy 和 deep copy 没区别

    复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

    不可变数据类型的copy

     
    
    1. #不可变数据类型的copy

    2. import copy

    3. a='123445'

    4. b=a

    5. c=copy.copy(a)

    6. d=copy.deepcopy(a)

    7. print('a===%s'%a)

    8. print('b===%s'%b)

    9. print('c===%s'%c)

    10. print('id(a)是:',id(a))

    11. print('id(b)是:',id(b))

    12. print('id(c)是:',id(c))

     结果是:

     
    
    1. a===123445

    2. b===123445

    3. c===123445

    4. id(a)是: 3113366507904

    5. id(b)是: 3113366507904

    6. id(c)是: 3113366507904

    分析:不可变的数据类型,等于赋值、浅复制、深复制id都是一样的。

    可变数据类型(列表、字典)的copy(元素不包含复杂元素):

     
    
    1. #可变数据类型的copy

    2. import copy

    3. l1=[1,2,3,4,5,6]

    4. l2=l1

    5. l3=copy.copy(l1)

    6. l4=copy.deepcopy(l1)

    7. l1.append('hello')

    8. l3[3]='world'

    9. print('l1====%s'%l1)

    10. print('l2====%s'%l2)

    11. print('l3====%s'%l3)

    12. print('l4====%s'%l4)

    13. l4.append('list')

    14. print('l4修改后为====%s'%l4)

    15. print('id(l1)是:',id(l1))

    16. print('id(l2)是:',id(l2))

    17. print('id(l3)是:',id(l3))

    18. print('id(l4)是:',id(l4))

    结果为:

     
    
    1. l1====[1, 2, 3, 4, 5, 6, 'hello']

    2. l2====[1, 2, 3, 4, 5, 6, 'hello']

    3. l3====[1, 2, 3, 'world', 5, 6]

    4. l4====[1, 2, 3, 4, 5, 6]

    5. l4修改后为====[1, 2, 3, 4, 5, 6, 'list']

    6. id(l1)是: 1510329127816

    7. id(l2)是: 1510329127816

    8. id(l3)是: 1510329128008

    9. id(l4)是: 1510329129288

    分析:可变数据类型的浅copy()方法,并不会修改被复制对象。

    可变数据类型包含复杂元素的copy:

     
    
    1. >>> import copy

    2. >>> list1=[1,2,3,['hello','hey','hi']]

    3. >>> list2=list1

    4. >>> list3=copy.copy(list1)

    5. >>> list4=copy.deepcopy(list1)

    6. >>> id(list1)

    7. 2380371448840

    8. >>> id(list2)

    9. 2380371448840

    10. >>> id(list3)

    11. 2380371450056

    12. >>> id(list4)

    13. 2380371450120

    14. >>> list1[3].append('list') #改变被复制对象内的列表项,浅复制的也跟着改变了,但是深复制的没有改变

    15. >>> id(list1)

    16. 2380371448840

    17. >>> list2

    18. [1, 2, 3, ['hello', 'hey', 'hi', 'list']]

    19. >>> id(list2)

    20. 2380371448840

    21. >>> list3

    22. [1, 2, 3, ['hello', 'hey', 'hi', 'list']]

    23. >>> id(list3)

    24. 2380371450056

    25. >>> list4

    26. [1, 2, 3, ['hello', 'hey', 'hi']]

    27. >>> id(list4)

    28. 2380371450120

    29. >>> list3[3][0]=0 #改变浅复制得到的对象内的列表,被复制对象也改变了,深复制对象没改变

    30. >>> list3

    31. [1, 2, 3, [0, 'hey', 'hi', 'list']]

    32. >>> list1

    33. [1, 2, 3, [0, 'hey', 'hi', 'list']]

    34. >>> id(list1)

    35. 2380371448840

    36. >>> id(list3)

    37. 2380371450056

    38. >>> list4

    39. [1, 2, 3, ['hello', 'hey', 'hi']]

    40. >>> id(list4)

    41. 2380371450120

    42. >>> list4.append('hahahha') #改变深复制的来的对象内的一般项,被复制对象没有改变

    43. >>> list4

    44. [1, 2, 3, ['hello', 'hey', 'hi'], 'hahahha']

    45. >>> list1

    46. [1, 2, 3, [0, 'hey', 'hi', 'list']]

    47. >>> list3

    48. [1, 2, 3, [0, 'hey', 'hi', 'list']]

    49. >>> id(list1)

    50. 2380371448840

    51. >>> id(list3)

    52. 2380371450056

    53. >>> id(list4)

    54. 2380371450120

    55. >>> list4[3][0]=1 #改变深复制的来的对象内的列表对象,被复制对象没有改变,浅复制对象也没改变

    56. >>> list4

    57. [1, 2, 3, [1, 'hey', 'hi'], 'hahahha']

    58. >>> list1

    59. [1, 2, 3, [0, 'hey', 'hi', 'list']]

    60. >>> list3

    61. [1, 2, 3, [0, 'hey', 'hi', 'list']]

    62. >>> id(list4)

    63. 2380371450120

    64. >>> id(list1)

    65. 2380371448840

    66. >>> id(list3)

    67. 2380371450056

    68. >>> list1.append('change')

    69. >>> list1

    70. [1, 2, 3, ['list1', 'hey', 'hi', 'list'], 'change']

    71. >>> list3

    72. [1, 2, 3, ['list1', 'hey', 'hi', 'list']] #改变被复制对象的一般元素时,浅复制对象没有改变

    73. >>> list4

    74. [1, 2, 3, [1, 'hey', 'hi'], 'hahahha']

    75. >>> #从始至终,每个对象的id没有改变过

    分析:

    1.改变被复制对象的一般元素时,浅复制对象没有改变,深复制对象没改变

    2.改变被复制对象的复杂子项中的元素时,浅复制对象跟着改变了,深复制对象没改变

    3.改变浅复制对象的一般项时,被复制对象没有改变,深复制对象没有改变

    4.改变浅复制对象的复制子项内的元素时,被复制对象改变了,深复制对象没有改变

    5.改变深复制对象的一般项时,被复制对象没有改变,浅复制对象没有改变

    6.改变深复制对象的复制子项内的元素时,被复制对象没有改变,浅复制对象没有改变

    python的数据存储方式

    Python 存储变量的方法跟其他 OOP 语言不同。它与其说是把值赋给变量,不如说是给变量建立了一个到具体值的 reference。

    当在 Python 中 a = something 应该理解为给 something 贴上了一个标签 a。当再赋值给 a 的时候,就好象把 a 这个标签从原来的 something 上拿下来,贴到其他对象上,建立新的 reference。 这就解释了一些 Python 中可能遇到的诡异情况:

     
    1. >> a = [1, 2, 3]

    2. >>> b = a

    3. >>> a = [4, 5, 6] //赋新的值给 a

    4. >>> a

    5. [4, 5, 6]

    6. >>> b

    7. [1, 2, 3]

    8. # a 的值改变后,b 并没有随着 a 变

    9. >>> a = [1, 2, 3]

    10. >>> b = a

    11. >>> a[0], a[1], a[2] = 4, 5, 6 //改变原来 list 中的元素

    12. >>> a

    13. [4, 5, 6]

    14. >>> b

    15. [4, 5, 6]

    16. # a 的值改变后,b 随着 a 变了

    上面两段代码中,a 的值都发生了变化。区别在于,第一段代码中是直接赋给了 a 新的值(从 [1, 2, 3] 变为 [4, 5, 6]);而第二段则是把 list 中每个元素分别改变。而对 b 的影响则是不同的,一个没有让 b 的值发生改变,另一个变了。怎么用上边的道理来解释这个诡异的不同呢?首次把 [1, 2, 3] 看成一个物品。a = [1, 2, 3] 就相当于给这个物品上贴上 a 这个标签。而 b = a 就是给这个物品又贴上了一个 b 的标签。 

     
    第一种情况:a = [4, 5, 6] 就相当于把 a 标签从 [1 ,2, 3] 上撕下来,贴到了 [4, 5, 6] 上。在这个过程中,[1, 2, 3] 这个物品并没有消失。 b 自始至终都好好的贴在 [1, 2, 3] 上,既然这个 reference 也没有改变过。 b 的值自然不变。

     
     

    第二种情况:a[0], a[1], a[2] = 4, 5, 6 则是直接改变了 [1, 2, 3] 这个物品本身。把它内部的每一部分都重新改装了一下。内部改装完毕后,[1, 2, 3] 本身变成了 [4, 5, 6]。而在此过程当中,a 和 b 都没有动,他们还贴在那个物品上。因此自然 a b 的值都变成了 [4, 5, 6]。

    搞明白这个之后就要问了,对于一个复杂对象的浅copy,在copy的时候到底发生了什么? 
    再看一段代码:

     
    1. >>> import copy

    2. >>> origin = [1, 2, [3, 4]]

    3. #origin 里边有三个元素:1, 2,[3, 4]

    4. >>> cop1 = copy.copy(origin)

    5. >>> cop2 = copy.deepcopy(origin)

    6. >>> cop1 == cop2

    7. True

    8. >>> cop1 is cop2

    9. False

    10. #cop1 和 cop2 看上去相同,但已不再是同一个object

    11. >>> origin[2][0] = "hey!"

    12. >>> origin

    13. [1, 2, ['hey!', 4]]

    14. >>> cop1

    15. [1, 2, ['hey!', 4]]

    16. >>> cop2

    17. [1, 2, [3, 4]]

    18. #把origin内的子list [3, 4] 改掉了一个元素,观察 cop1 和 cop2

    学过docker的人应该对镜像这个概念不陌生,我们可以把镜像的概念套用在copy上面。

    copy概念图如下: 

    copy(浅复制)对于一个复杂对象的子对象并不会完全复制,什么是复杂对象的子对象呢?就比如序列里的嵌套序列字典里的嵌套序列等都是复杂对象的子对象。对于子对象,python会把它当作一个公共镜像存储起来,所有对他的复制都被当成一个引用,所以说当其中一个引用将镜像改变了之后另一个引用使用镜像的时候镜像已经被改变了

    所以说看这里的origin[2],也就是 [3, 4] 这个 list。根据 shallow copy 的定义,在 cop1[2] 指向的是同一个 list [3, 4]。那么,如果这里我们改变了这个 list,就会导致 origin 和 cop1 同时改变。这就是为什么上边 origin[2][0] = “hey!” 之后,cop1 也随之变成了 [1, 2, [‘hey!’, 4]]。

    deepcopy概念图如下: 

    deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。 
    这时候的 origin[2] 和 cop2[2] 虽然值都等于 [3, 4],但已经不是同一个 list了。即我们寻常意义上的复制。

    展开全文
  • DeepCopy 可帮助您创建对象的深层副本(克隆)。 它旨在处理关联图中的循环。 您如何创建对象的深层副本(即也复制属性中引用的所有对象)? 您使用 __clone() 并自己实现该行为。 DeepCopy 递归遍历对象的所有属性...
  • 目录 1. API简介 2. 基本使用 3. 拷贝函数 4. 指定拷贝深度 5. 循环引用 6. 保持类型信息 7. 拷贝不可枚举的属性 8. 自定义拷贝规则 8.1. typeCopyers 8.1.1. Types 8.1.2. 拷贝者Copyer ...import {deepCopy
  • python中copy()和deepcopy()详解

    千次阅读 2021-03-17 15:29:15
    deepcopy概念图如下: deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。 这时候的 origin[2] 和 cop2[2] 虽然值都等于 [3, 4],但已经不是同一个 list了。即我们寻常意义上的复制。
  • copy与deepcopy区别

    千次阅读 2022-04-28 12:24:30
    copy与deepcopy区别
  • 2. copy.deepcopy 深拷贝 拷贝对象及其子对象一个很好的例子: import copya = [1, 2, 3, 4, [‘a’, ‘b’]] #原始对象b = a #赋值,传对象的引用c = copy.copy(a) #对象拷贝,浅拷贝d = copy....
  • python中copy和deepcopy详解

    千次阅读 2022-05-29 11:35:56
    deepcopy是真正意义上的复制,深拷贝,被复制对象完全复制一遍作为独立的新个体,新开辟一块空间。 浅拷贝,不会产生独立对象,等于赋值,只是对原有数据块打上新标签,其中一个标签改变,数据块就会变化。浅拷贝...
  • 1、对于数值、字符串和元组,不同的复制方式没有区别,复制后,=/copy/deepcopy的id不变。改变原对象的内容,不会改变新对象的内容。 2、对于数值、字符串和元组,只能通过赋值来修改这些对象,修改后id会发生变化。...
  • DeepCopy-ShallowCopy:DeepCopy&ShallowCopy
  • lst1[3][0] = 100 print('4-----:id(lst1)=',id(lst1),lst1) print('5-----:id(lst2)=',id(lst2),lst2) print('6-----:id(lst2)=',id(lst3),lst3) print('*'*10,'使用deepcopy拷贝:') import copy lst1 = [1,2,...
  • 手写深拷贝deepCopy

    2022-06-03 11:37:35
    deepCopy
  • js实现deepCopy

    2021-03-25 15:43:53
    function deepCopy(obj) { if (typeof obj === 'object') { var result = obj.constructor === Array ? [] : {}; for (var i in obj) { result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i]; } } ...
  • deepcopy_submodules

    2021-04-05 07:18:32
    子模块的深层复制这个bash程序有助于将具有许多子模块的git项目从私有区域(例如LAN)迁移或部署到公共区域(例如github)。 ·目录关于该项目 这个bash程序有助于将具有许多子模块的git项目从私有区域(例如LAN)...
  • 大家好,我是胡亥大魔王。今天介绍python中引用、copy() 及 deepcopy() 的使用
  • 其实复制Java数组的方法很多,但大多数都是浅层复制,今天爱站技术频道小编带你寻找详解JAVA 深层拷贝 DeepCopy的使用方式。方法实现很简单,提供两种方式:一种是序列化成数据流,前提是所有对象(对象中包含的对象....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 46,663
精华内容 18,665
关键字:

deepcopy

友情链接: 效果器升级软件33.rar