博客参考:点击这里

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()

 

 

 

写在后面:

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