精华内容
下载资源
问答
  • python中deepcopy的用法
    千次阅读
    2020-12-30 01:34:10

    copy.deepcopy()的用法是将某一个变量的值赋值给另一个变量(此时两个变量地址不同),因为地址不同,所以可以防止变量间相互干扰。

    大家可以猜猜下面代码第四行输出什么值

    例1.

    a = [1, 2, 3]

    d = a # a和d的地址相同, 看第5行的输出

    a[0] = 2

    print(d)

    print(id(a), id(b)) # id() 输出a和d变量的地址

    答案是:[2 2 3]

    [2, 2, 3]

    2063948923080 2063948923080

    原因是通过赋值的方式使得d和a的地址相同,即d和a指向内存中的同一个地址。

    而且改变d中的值,a也会随着改变,自己可以尝试一下。

    如果想让a和d两个变量互不影响,就用copy.deepcopy()函数

    例2.

    import copy

    a = [1, 2, 3]

    d = copy.deepcopy(a) # a和d的地址不相同

    a[0] = 2

    print(d)

    print(id(a), id(d))

    输出:

    [1, 2, 3]

    2793378037960 2793379617288

    思考下面代码会输出什么:

    例3.

    a = [1, 2, 3]

    d = a

    c = 1 # 注意 1其实也有地址,而且这个地址是固定的,不会随程序发生改变。

    a = c

    print(d)

    如果你有点绕不开了,先看看答案吧。

    答案是:

    [1, 2, 3]

    也许你奇怪a和d的地址不是一样的吗,怎么改变了a,d还是不变了。原因很简单,因为c的地址和a的地址不同,把c赋值给a,则a的地址和c的地址相同,但d的地址在初始时就已经是a原先的地址了。即使a的地址后来发生了变化,d的地址也不受影响。

    通过以上的介绍你可能会认为

    只要两个变量的地址不同,则两者之间不会相互影响,否则就会

    。真的是这样吗?

    上面的例子比较简单,可以这么认为。再补充几个例子,看看程序的输出与自己想象的结果是否一样:

    例4.

    import numpy as np

    a = np.array([[1,2,3], [5,5,5]])

    d = a.transpose(1,0)

    print(id(d), id(a)) # a和d的地址不同,但d会受a的影响,当然a也会受d影响

    a[0, 0] = 9

    print(d)

    输出:

    2129658874816 2129658874576

    [[9 5]

    [2 5]

    [3 5]]

    例5

    import numpy as np

    a = np.array([1, 2, 3])

    b = np.array([1, 5, 6])

    c = np.array([a, b])

    print(id(a), id(c), id(c[0])) # 虽然c[0]值等于a,但c[0]和a的地址不同

    a[0] = 9

    print(c)

    输出:

    2204876507856 2204879229216 2204879229296

    [[1 2 3]

    [1 5 6]]

    例6

    import numpy as np

    a = np.array([1, 2, 3])

    b = np.array([1, 5, 6])

    c = a - b

    a[0] = 9

    print(c)

    输出:

    [ 0 -3 -3]

    例7.

    import numpy as np

    c = np.array([[3, 2, 3], [5, 7, 8]])

    e = c[0]

    e[0] = 9

    print(c)

    print(id(e), id(c[0]), id(c[1]), id(c)) # e和c的地址不同,但和c[0]相同

    输出:

    [[9 2 3]

    [5 7 8]]

    1965873400768 1965876121968 1965876121968 1965873400528

    总结:①从例5,6可以看出,如果一个变量由多个变量通过某种方式(拼接或加减)得来的,则这个变量不会受其他变量的影响。但结合例7,如果一个变量e来自另一个变量c的某一部分值,则改变量e的值(不改变e的地址时),变量c也会受影响。②从例4可知,虽然两个变量a,d地址不同,但d是通过a经过自身变换(转置,只改变形状)而来,所以改变某一个变量内的值,另一个变量也会跟着改变。所以说并不能单纯地认为变量地址不同,变量间就不会相互影响。所以为了防止变量间相互影响,使用copy.deepcopy()方法最为安全。

    更多相关内容
  • python中copy和deepcopy详解

    千次阅读 2022-05-29 11:35:56
    python中标识一个对象唯一身份的是:对象的id(内存地址),对象类型,对象值。 deepcopy是真正意义上的复制,深拷贝,被复制对象完全复制一遍作为独立的新个体,新开辟一块空间。 浅拷贝,不会产生独立对象,等于赋值...

    python中标识一个对象唯一身份的是:对象的id(内存地址),对象类型,对象值。

    deepcopy是真正意义上的复制,深拷贝,被复制对象完全复制一遍作为独立的新个体,新开辟一块空间。

    浅拷贝,不会产生独立对象,等于赋值,只是对原有数据块打上新标签,其中一个标签改变,数据块就会变化。浅拷贝等于赋值,也可以通过copy实现,copy仅拷贝对象本身,浅拷贝不会对其中的子对象进行拷贝,如果对子对象进行修改,拷贝结果也会随着修改。

    • 复制的对象中无复杂子对象,即列表中不嵌套列表,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。
    • 复制的对象中有复杂子对象 (例如列表中的一个子元素是一个列表)如果改变复杂子对象的值(列表中的值)会影响浅复制的值。
    import copy
    a = [1,2,3,[4,5],1]
    b = a
    c = copy.copy(a)
    d = copy.deepcopy(a)
    
    a.append(9)
    a[3].append(6)
    
    print(a) 	#[1, 2, 3, [4, 5, 6], 1, 9]
    print(b)	#[1, 2, 3, [4, 5, 6], 1, 9]
    print(c)	#[1, 2, 3, [4, 5, 6], 1]
    print(d)	#[1, 2, 3, [4, 5], 1]
    
    print(id(a))	#4594148288
    print(id(b))	#4594148288
    print(id(c))	#4594455328
    print(id(d))	#4592688496
    
    
    x = 'Hello World'
    y = x
    z = copy.copy(x)
    w = copy.deepcopy(x)
    print(id(x)) #4617118576
    print(id(y)) #4617118576
    print(id(z)) #4617118576
    print(id(w)) #4617118576
    
    # 对于不可变类型(元组、数值,字符串等)为浅拷贝,对象的id值与浅复制原来的值相同
    # 对于可变类型(列表、字典等)为深拷贝,
    
    展开全文
  • python中copy()和deepcopy()详解

    千次阅读 2021-03-17 15:29:15
    python的数据存储方式 Python 存储变量的方法跟其他 OOP 语言不同。它与其说是把值赋给变量,不如说是给变量建立了一个到具体值的 reference。 当在 Python a = something 应该理解为给 something 贴上了一个...

    **首先直接上结论: —–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。

    —–而浅复制并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。**

    对于简单的 object,用 shallow copy 和 deep copy 没区别

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

    看不懂文字没关系我们来看代码:

    >>> import copy

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

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

    >>> cop1 = copy.copy(origin)

    >>> cop2 = copy.deepcopy(origin)

    >>> cop1 == cop2

    True

    >>> cop1 is cop2

    False

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

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

    >>> origin

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

    >>> cop1

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

    >>> cop2

    [1, 2, [3, 4]]

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

    可以看到 cop1,也就是 shallow copy 跟着 origin 改变了。而 cop2 ,也就是 deep copy 并没有变。

    似乎 deep copy 更加符合我们对「复制」的直觉定义: 一旦复制出来了,就应该是独立的了。如果我们想要的是一个字面意义的「copy」,那就直接用 deep_copy 即可。

    那么为什么会有 shallow copy 这样的「假」 copy 存在呢? 这就是有意思的地方了。

    python的数据存储方式

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

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

    >> a = [1, 2, 3]

    >>> b = a

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

    >>> a

    [4, 5, 6]

    >>> b

    [1, 2, 3]

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

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

    >>> b = a

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

    >>> a

    [4, 5, 6]

    >>> b

    [4, 5, 6]

    # 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 的标签。

    d9b564759210d1dc3aea6633e5cf0d8b.png

    第一种情况:

    a = [4, 5, 6] 就相当于把 a 标签从 [1 ,2, 3] 上撕下来,贴到了 [4, 5, 6] 上。

    在这个过程中,[1, 2, 3] 这个物品并没有消失。 b 自始至终都好好的贴在 [1, 2, 3] 上,既然这个 reference 也没有改变过。 b 的值自然不变。

    29d623646a67e6e29e61bb477df9138e.png

    第二种情况:

    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的时候到底发生了什么?

    再看一段代码:

    >>> import copy

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

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

    >>> cop1 = copy.copy(origin)

    >>> cop2 = copy.deepcopy(origin)

    >>> cop1 == cop2

    True

    >>> cop1 is cop2

    False

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

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

    >>> origin

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

    >>> cop1

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

    >>> cop2

    [1, 2, [3, 4]]

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

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

    概念图如下:

    8c2b05cd89137cc4433870903be4e2f1.png

    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概念图如下:

    0e294ee34fe8c1c85bcf7ca9523bc1f7.png

    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概念图如下:

    38f41276aca358b09bbac82ded80263d.png

    deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。

    这时候的 origin[2] 和 cop2[2] 虽然值都等于 [3, 4],但已经不是同一个 list了。即我们寻常意义上的复制。

    展开全文
  • deepcopy内存问题

    关于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
    
    展开全文
  • python deepcopy

    千次阅读 2019-04-15 16:36:05
    1. copy.copy 浅拷贝 只...2. copy.deepcopy 深拷贝 拷贝对象及其子对象一个很好的例子: import copya = [1, 2, 3, 4, ['a', 'b']]  #原始对象b = ...
  • 简介 INTRODUCTION掌握python中字典数据的赋值处理,掌握指针到底在哪里?...本篇文章创作主要是为了让小伙伴们掌握普通字典的赋值、字典的copy复制赋值、deepcopy对字典的复制赋值 这三种不同的复制之间的区别。一...
  • List列表、Dict字典等对象经常进行常量赋值时,不能直接使用等于号=进行赋值(浅拷贝,只赋值了内存地址,相当于是引用),需要使用copy()方法进行对象复制 DICT_INIT = {'A': 0, 'B': 0} dictA = DICT_INIT.copy...
  • python copy.deepcopy()深入解读

    千次阅读 多人点赞 2020-09-17 20:52:55
    copy.deepcopy()的用法是将某一个变量的值赋值给另一个变量(此时两个变量地址不同),因为地址不同,所以这两个变量互不干扰。 大家可以猜猜下面代码第四行输出什么值 a = [1, 2, 3] d = a # a和d的地址相同, 看第5...
  • 前言copy()与deepcopy()之间的区分必须要涉及到python对于数据的存储方式。深复制被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。浅复制并不会产生...
  • python list的deepcopy过慢

    千次阅读 2021-11-21 16:12:43
    程序跑的很慢,使用bottleneck一分析发现问题出在deepcopy上。 因为程序是需要对列表进行操作,而我的程序逻辑是要求必须对列表进行深拷贝,于是没有办法绕过。 只能想办法加速这个深层拷贝。 我想到四种方法 第一种...
  • python中对于对象的拷贝分为浅拷贝(copy)和深拷贝(deepcopy)两种方式。其中浅拷贝由“=”完成。而深拷贝由copy模块中deepcopy()函数担任。 ** 浅拷贝和深拷贝的区别是:浅拷贝只是将原对象在内存引用地址拷贝过来...
  • #------------------------------------------------我是可耻的分割线-------------------------------------------在处理列表和字典时,尽管传递引用常常是最方便的方法,但如果函数修改了传入的列表或字典,你可能...
  • Python中deepcopy 和copy的区别

    千次阅读 2018-01-07 21:33:24
    最近在使用Python语言编程的过程遇见了deepcopy()方法,想着这个名字比较特别,于是网上找了一下参考资料,索性比较了与copy()的区别。两者区别如下: —–deepcopy(): 深复制,即将被复制对象完全再复制一遍...
  • 在new_module.pyfrom old_module import implementation as _implementation def implementation(arg1, arg2): """a different docstring""" return _implementation(arg1, arg2) 这是重用功能的最直接的方法。...
  • 之所以提出这个问题,是因为有这样一个场景,我需要使用两个列表ls_old与ls_new分别记录某一组状态在执行前后的值,以此判断执行是否成功。若执行成功,则ls_old=ls_new以保存当前状态 因为采用的是=赋值方式,当...
  • python3,直接可以使用copy()方法,但deepcopy()还是需要导入copy模块 下面以python2为例: import copy list = ['beijing','tianjin','hebei','wuhan','shandong'] list_copy = copy.copy(list) list[0] = '...
  • python调试,使用print打印出中间结果容易发现问题。由于python3的map需要list转换后才能print出具体的内容。...具体使用方法如下: # 计算特征集中每个特征的信息增益 l = map(lambda x: [x...
  • python3,直接可以使用copy()方法,但deepcopy()还是需要导入copy模块 >首先直接上结论: —–深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制...
  • 我有一个非常简单的python例程,它涉及循环遍历大约20000个纬度、经度坐标的列表,并计算每个点到参考点的距离。def compute_nearest_points( lat, lon, nPoints=5 ):"""Find the nearest N points, given the input...
  • 我有一个dict,其值是非嵌套...我知道我可以使用copied = copy.deepcopy(original)但是,由于我知道数据结构的形式,我也可以使用类似的东西copied = {key:valuelist[:] for (key,valuelist) in original.iteritems()}...
  • 在工作,常涉及到数据的传递,在数据传递使用过程,可能会发生数据被修改的问题。...今天就说一下Python中的深浅拷贝问题。一、深浅copy1. 赋值运算l1=[1,2,3,[22,33]]l2=l1l1.append(666)print(l1)#[1,2,3,[...
  • hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。该函数的语法格式如下: hasattr(obj, name) 其中 obj 指的是某个类的实例对象,name 表示指定的属性名或方法名。同时,该函数会将判断的结果...
  • Python中copy()和deepcopy()的区别

    千次阅读 2019-02-24 20:26:19
    同样是copy,二者有什么不同呢今天我们就一探究竟!!! python——赋值与深浅拷贝  初学编程的小伙伴都会对于深浅拷贝的... 在详细的了解python中赋值、copy和deepcopy之前,我们还是要花一点时间来了解一下p...
  • 根据 莫烦Python的教程 总结写成,以便自己复习和使用,这里我就不哟林地挂原创了????。 copy a8 = np.arange(4) b8 = a8 c8 = a8 d8 = b8 a8[0] = 11 print(a8,b8,c8,d8)# pyhton 赋值是完完全全相等的,改变其中...
  • python写代码实现list的deepcopy

    千次阅读 2017-03-21 11:14:49
    python有copy.copy()和copy.deepcopy()这两个函数分别提供浅拷贝和深拷贝的功能。今天突然想自己写代码实现list深拷贝的功能,于是写完了在这里分享一下(本文不涉及list之外的对象的深拷贝)。首先,给出一个套叠了...
  • 返回一个代理对象, 这个对象负责将方法调用分配给第一个参数的一个父类或者同辈的类去完成. parent or sibling class 如何确定? 第一个参数的__mro__属性决定了搜索的顺序, super指的的是 MRO(Method Resolution ...
  •   最近要用多进程编程提高程序对CPU的利用率,我使用了multiprocessing.Queue完成各进程之间需要通信。伪代码如下: 用于存储数据的类: class dataSaving: list1 list2 data_append_method(x, y): ...
  • 我有一个非常简单的python例程,其中涉及循环遍历大约20,000个纬度,经度坐标的列表,并计算每个点到参考点的距离。def compute_nearest_points( lat, lon, nPoints=5 ):"""Find the nearest N points, given the ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,969
精华内容 5,987
热门标签
关键字:

python中deepcopy的用法