Python中的复制,深拷贝和浅拷贝
- Python是基于值的内存管理方式。
- 在Python中,对象赋值实际上是对象的引用。
- 当创建一个对象,然后把它赋值给另一个变量的时候,Python并没有拷贝这个对象,而只是拷贝了这个对象的引用,即共同指向一个地址。
Python中的的复制有以下三种:
- (1)直接赋值:
- 默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的列表也会做相同改变。
>>>a = [0, 1, [2, 3]] >>>b = a >>>b [0, 1, [2, 3]] >>>id(a) 00000000000 >>>id(b) 00000000000 >>>a.append(4) # id(a)=id(b) >>>a [0, 1, [2, 3], 4] >>>b [0, 1, [2, 3], 4]
- (2)copy浅拷贝:
- 没有拷贝子对象,所以原始数据改变,子对象会改变。
>>>import copy >>>a = [0, 1, [2, 3]] # 只拷贝顶层对象,不拷贝子对象 >>>c = copy.copy(a) >>>id(a) 00000000000 >>>id(C) 11111111111 # id(a)不等于id(c) >>>a.append(4) >>>a [0, 1, [2, 3], 4] >>>c [0, 1, [2, 3]] >>>a[2] [2, 3] >>>id(a[2]) 33333333333 >>>id(c[2]) 33333333333 # id(a[2])=id(c[2]) # 改变a里面的子对象 >>>a[2].append(4) >>>a[2] [2, 3, 4] >>>c[2] [2, 3, 4] # a[2]=c[2]
- (3)deepcopy深拷贝:
- 拷贝包含对象里面的子对象,所以原始对象的改变不会造成深拷贝里面任何子元素的改变
- 优点:在以后做数据的清洗、修改或者入库的时候,对原数据进行复制一份,以防数据修改之后,找不到原数据。
>>>import copy >>>a = [0, 1, [2, 3]] # 拷贝包含对象里面的所有子对象 >>>c = copy.deepcopy(a) >>>id(a) 00000000000 >>>id(d) 11111111111 # id(a)不等于id(d) >>>id(a[2]) 33333333333 >>>id(d[2]) 44444444444 # id(a[2])不等于id(d[2])
对于不可变数据类型,copy和deepcopy的区别
- 当用copy()函数拷贝一个元组(不可变数据类型)时候,那么他不会进行浅拷贝,仅仅拷贝的是指向。
- 因为元组是不可变类型,那么意味着数据一定不能修改,因此用copy()函数的时候他会自动判断,如果是元组就指向了它。
- 如果拷贝一个全部都是不可变类型的数据,那么他们结果相同,都是拷贝指向,即拷贝引用。
- 如果拷贝一个拥有可变类型的数据,既是元组在最顶层,那么deepcopy()仍然是深拷贝,而copy()还是拷贝指向。