博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

二、Python开发---8、浅拷贝与深拷贝

Posted on 2019-09-23 14:28  兰智杰  阅读(235)  评论(0编辑  收藏  举报

浅拷贝与深拷贝

    可变(mutable)参数和不可变(immutable)参数

    Python中stringtuplenumber不可变对象,而dictlist等是可变对象;不可变对象在进行重新赋值的时候,实际上是将原始值丢弃,将变量指向一个新值;可变对象的可变性实质上是指更改可变对象中的子对象,比如list中的item元素的更改。

    下文中讨论的赋值,都是基于上述的条件之上的,即操作的都是可变对象(dict、list),如果操作的是不可变对象(string、tuple、number),则不适用。

    直接赋值:其实就是对象的引用(别名)。例如:b=a,则a,b指向的是同一内存,类似于同一事物的两个不同叫法。

a = [1,2,3]     #操作的是可变对象(dict、list)
b = a
print(id(a))    #通过id查看变量在内存中的地址 输出为1860168
print(id(b))                             #输出为1860168

a[0] = 5        #修改的是a
print(a)        #输出为[5, 2, 3]
print(b)        #输出为[5, 2, 3]

c=3             #操作的是不可变对象(string、tuple、number)
d=c
print(id(c))    #通过id查看变量在内存中的地址 输出为8791403107200
print(id(d))                             #输出为8791403107200

c=8             #修改的是c
print(c)        #输出为8
print(d)        #输出为3

    浅拷贝:不拷贝子对象(针对子对象中的item),当子对象进行更改的时候,原始对象也会改变。例如:b=a,不同于直接赋值,这里的b会重新分配一个内存,简而言之,就是a与b不同,但a与b指向的子对象是一样的,进而子对象改变,则a与b都会改变。

      常见操作:列表的切片[:]操作、list()操作,字典的copy()函数、copy模块的copy()函数(两个一模一样的双胞胎)

a = [1,2,3]
b = [11,22,33]
c = [111,222,333]

list01 = [a,b,c]
list02 = list01[:]
#查看list01 和 list02
print(list01)               #输出为[[1, 2, 3], [11, 22, 33], [111, 222, 333]]
print(list02)               #输出为[[1, 2, 3], [11, 22, 33], [111, 222, 333]]
#检查list01 和 list02 在内存中的地址
print(id(list01))           #输出为7155400
print(id(list02))           #输出为36013832  说明了是新分配的一个内存空间

#修改一下
a[0] = 5
print(list01)               #输出为[[5, 2, 3], [11, 22, 33], [111, 222, 333]]
print(list02)               #输出为[[5, 2, 3], [11, 22, 33], [111, 222, 333]]
list01 = [a,c,b]
print(list01)               #输出为[[5, 2, 3], [111, 222, 333], [11, 22, 33]]
print(list02)               #输出为[[5, 2, 3], [11, 22, 33], [111, 222, 333]]
#上述语句说明了list01与list02分配的内存空间不一样,但其子对象均指向a,b,c

    深拷贝:会拷贝子对象,当对原始对象子对象进行更改的时候,原始对象不会改变。例如:b=a,这里的b也是会重新分配一个内存,但a与b已经完全没有关系了,对a以及其子对象的操作,完全不改变b。

      常见操作:copy模块的deepcopy()函数

import copy
a = [1,2,3]
b = [11,22,33]
c = [111,222,333]
list01 = [a,b,c]
list02 = copy.deepcopy(list01)
print(list01)               #输出为[[1, 2, 3], [11, 22, 33], [111, 222, 333]]
print(list02)               #输出为[[1, 2, 3], [11, 22, 33], [111, 222, 333]]
#检查list01 和 list02 在内存中的地址
print(id(list01))           #输出为42323336
print(id(list02))           #输出为42323016  说明了是新分配的一个内存空间

#修改一下
a[0] = 5
# print(a)
print(list01)               #输出为[[5, 2, 3], [11, 22, 33], [111, 222, 333]]
print(list02)               #输出为[[1, 2, 3], [11, 22, 33], [111, 222, 333]]
#上述语句说明了list01与list02分配的内存空间不一样,同时会拷贝子对象,这时两者完全无关了