zoukankan      html  css  js  c++  java
  • 浅谈python 复制(深拷贝,浅拷贝)

    博客参考:点击这里

    python中对象的复制以及浅拷贝,深拷贝是存在差异的,这儿我们主要以可变变量来演示,不可变变量则不存在赋值/拷贝上的问题(下文会有解释),具体差异如下文所示

    1.赋值:

    1 a=[1,2,3]
    2 b=a
    3 a.append('3')
    4 print 'b=',b

      实例输出结果如下:

    1 b= [1, 2, 3, '3']

      这儿我们只对列表a进行了操作,但列表b也随之改变,根本原因是在进行赋值操作的时候,变量a与变量b指向了相同的内存地址,实例如下:

    1 #coding=utf-8
    2 a=[1,2,3]
    3 b=a
    4 print "变量a的内存地址:",id(a) #获取变量的内存地址
    5 print "变量b的内存地址:",id(b)
    6 a.append(4)
    7 print "变量a的内存地址:",id(a)
    8 print "变量b的内存地址:",id(b)

    输出结果如下:

    1 变量a的内存地址: 39012592
    2 变量b的内存地址: 39012592
    3 变量a的内存地址: 39012592
    4 变量b的内存地址: 39012592

      以上结果可以看出进行赋值操作时变量与变量b的内存地址一致,故而在变量a值发生改变时,变量b的值也随之改变。

      但这种情况只针对可变变量,str属于不可变变量,值发生改变的时候会重新申请新的地址,实例如下:

    1 #coding=utf-8
    2 a='123'
    3 print ' 变量a的内存地址:',id(a)
    4 a='234'
    5 print ' 变量a的内存地址:',id(a)

      输出结果如下:

    1  变量a的内存地址: 38734832
    2  变量a的内存地址: 38734856

    2.浅拷贝(copy.copy())

    1 #coding=utf-8
    2 import copy
    3 a=[1,2,3]
    4 b=copy.copy(a)
    5 print ' 变量a的内存地址:',id(a)
    6 print ' 变量b的内存地址:',id(b)
    7 a.append(4)
    8 print b

      输出结果:

    1  变量a的内存地址: 38160664
    2  变量b的内存地址: 38203224
    3 [1, 2, 3]

      因为变量a与变量b的内存地址不一样,故而在变量a发生改变时,变量b未改变,但因为浅拷贝依然会使用原始变量中元素的地址,实例如下:

    1 #coding=utf-8
    2 import copy
    3 a=[1,2,3]
    4 b=copy.copy(a)
    5 for i in  range(0,len(a)):
    6     print ' 变量a中第%d的内存地址:%d'%(i,id(a[i]))
    7 for i in  range(0,len(b)):
    8     print ' 变量b中第%d的内存地址:%d'%(i,id(b[i]))

      输出结果:

    1  变量a中第0的内存地址:33860840
    2  变量a中第1的内存地址:33860828
    3  变量a中第2的内存地址:33860816
    4  变量b中第0的内存地址:33860840
    5  变量b中第1的内存地址:33860828
    6  变量b中第2的内存地址:33860816

      由输出结果可知,变量a和变量b中的元素的内存地址是一致的,当变量a中存在可变元素时,对可变元素进行更改,变量b依然会同时进行更改,实例如下:

    1 #coding=utf-8
    2 import copy
    3 a=[1,2,3,[11,2,3]]
    4 b=copy.copy(a)
    5 print '变量a修改前,b的内容:',b
    6 a[3].append(4)
    7 print  '变量a修改后,b的内容:',b

      输出如下:

    1 变量a修改前,b的内容: [1, 2, 3, [11, 2, 3]]
    2 变量a修改后,b的内容: [1, 2, 3, [11, 2, 3, 4]]

    3.深拷贝(copy.deepcopy())

    1 #coding=utf-8
    2 import copy
    3 a=[1,2,3,[11,2,3]]
    4 b=copy.deepcopy(a)
    5 for i in  range(0,len(a)):
    6     print ' 变量a中第%d的内存地址:%d'%(i,id(a[i]))
    7 for i in  range(0,len(b)):
    8     print ' 变量b中第%d的内存地址:%d'%(i,id(b[i]))

      输出如下:

    1  变量a中第0的内存地址:30518504
    2  变量a中第1的内存地址:30518492
    3  变量a中第2的内存地址:30518480
    4  变量a中第3的内存地址:38553880
    5  变量b中第0的内存地址:30518504
    6  变量b中第1的内存地址:30518492
    7  变量b中第2的内存地址:30518480
    8  变量b中第3的内存地址:38643072

      变量a与变量b中的每一个元素的内存地址都不相同,故而变量a发生改变时,变量b不会随之改变。

    总结:

      1.赋值,浅拷贝,深拷贝只针对可变变量,如list,dict,tuple

      2.python中赋值都是进行内存地址的传递

      3.浅拷贝(copy,copy())只会赋值对象,重新申请内存地址,但对于对象中的元素依然是原始的内存地址引用

      4.如果要完全拷贝一个对象,请使用copy.deepcopy()

    写在后面:

      每天写一点,总有一天我这条咸鱼能变得更咸

  • 相关阅读:
    J. 最大权边独立集 题解(树上背包)
    F. 地图压缩 题解(kmp 最小循环节)
    Sum of Log 题解(数位dp)
    F. Scalar Queries 题解(思维+线段树)
    B. 攻防演练 题解(思维+倍增)
    Bit Sequence 题解(数位dp)
    机器学习
    Android学习笔记
    sqoop
    Initialization failed for block pool Block pool
  • 原文地址:https://www.cnblogs.com/gj5379/p/7674127.html
Copyright © 2011-2022 走看看