深浅拷贝
赋值(基本数据类型)
Python中,所谓的赋值实际上就是对象引用的传递
当创建一个对象的时候,再赋值给另外一个变量的时候,是把这个变量在地址空间的id地址值传递给另一个变量,简单的说就是拷贝了这个对象的引用。
主要的操作,栈内存的复制
>>> a=1
>>> b=a
>>> id(a)
140734331088640
>>> id(b)
140734331088640
浅拷贝
浅拷贝是对一个对象父级(外层)的拷贝,并不会拷贝子级(内部)。使用浅拷贝的时候,分为两种情况。
>>> a=[1,2]
>>> b=[3,4]
>>> c=[a,b]
>>> d=copy.copy(c)
>>> id(d)
2518098905416
>>> id(c)
2518098905736
>>> id(d[0])
2518098717064
>>> id(c[0])
2518098717064
对于c和d来说是一个列表,是可变的,所以浅拷贝时,id地址会发生变化,但是c和d内部的元素也是列表对象,但是内部的对象不会拷贝,所以id地址不变
第一种
如果最外层的数据类型是可变的,比如说列表,字典等,浅拷贝会开启新的地址空间去存放。
赋值:
>>> list = [1,2,3,4]
>>> id(list)
2518066946632
>>> lt = list
>>> id(lt)
2518066946632
浅拷贝:
>>> import copy
>>> ls = copy.copy(list)
>>> id(ls)
2518098812040
地址发生变化
第二种
如果最外层的数据类型是不可变的,比如元组,字符串等,浅拷贝对象的时候,还是引用对象的地址空间。
浅拷贝:
>>> str = '123456'
>>> str1 = copy.copy(str)
>>> id(str)
2518098724264
>>> id(str1)
2518098724264
地址没有发生变化
深拷贝
深拷贝对一个对象是所有层次的拷贝(递归),内部和外部都会被拷贝过来。
>>> d=copy.deepcopy(c)
>>> id(c)
1408115280264
>>> id(d)
1408115279944
>>> id(c[0])
1408115186504
>>> id(c[1])
1408115091144
>>> id(d[0])
1408115279880
深拷贝的内部对象和外部对象地址都是不一样的
深拷贝
也分两种情况:
第一种
最外层数据类型可变。这个时候,内部和外部的都会拷贝过来。
>>> d=copy.deepcopy(c)
>>> id(c)
1408115280264
>>> id(d)
1408115279944
>>> id(c[0])
1408115186504
>>> id(c[1])
1408115091144
>>> id(d[0])
1408115279880
第二种
外层数据类型不可变,如果里面是可变数据类型,会新开辟地址空间存放。如果内部数据类型不可变,才会如同浅拷贝一样,是对地址的引用。
外层数据:
>>> tuple=('1','2',['3'])
>>> te = copy.deepcopy(tuple)
>>> id(tuple)
1408115001816
>>> id(te)
1408115260944
id是不一样的
内层数据:
>>> id(tuple[0])
1408111993160
>>> id(te[0])
1408111993160
>>> id(tuple[2])
1408115280200
>>> id(te[2])
1408115280520
不同的类型是不一样的,不可变数据的id是一样的,可变数据的id是不一样的
1、需要将当前对象拷贝的时候,一般建议拷贝为浅拷贝,(效率高,内存占有少)
2、如果说,就是需要完全分离,请使用深拷贝
结论:
元组、字符串、数值这些不可变类型,所有深浅拷贝后,永远只有一份内存
注意特殊情况,如元组中的存在可变类型的元素