Python中的浅拷贝和深拷贝

浅拷贝 赋值 和 copy.copy()

Python中的浅拷贝分为直接赋值和使用copy模块的copy方法来进行浅拷贝。

赋值

先来看直接赋值的例子:

a = [1,2,3]

b = a

print( b is a) # True

很简单,就是两个变量指向同一个内存地址。

copy.copy()

  • 对于不可变类型来说
    对于不可变类型,copy.copy()的表现形式和直接赋值是一样的,并不会重新创建一个新的对象,而是仅仅把新的变量指向原先的同一个地址上:
import copy

a = [1,2,3]
b= [4,5,6]

c = (a,b) # c为不可变类型

print( id(c) ) # 140065869930632

d = copy.copy(c)
print( id(d) ) # 140065869930632
print(d is c) # True

可以看到,对于不可变类型,使用d = copy.copy(c)就相当于直接赋值d = c

  • 对于可变类型来说
    对于可变类型,copy.copy()会创建于一块新的内存地址,然后仅仅拷贝目标对象的第一层,来看例子:
import copy

a = [1,2,3]
b= [4,5,6]

c = [a,b] # c为可变类型

d = copy.copy(c)

print( id(c) ) # 140393314515528
print( id(d) ) # 140393343993800
print(d is c) # False
# 说明创建了一块新的内存地址

a.append(4)
print(c) # [[1, 2, 3, 4], [4, 5, 6]]
print(d) # [[1, 2, 3, 4], [4, 5, 6]]

上述例子中,可以看到copy()是创建了一个新的内存地址的,但是并没有将内部的a和b的两个引用也一起拷贝,而是仅仅拷贝了第一层,所以改变了a指向的对象之后,浅拷贝出来的d也会相应的改变。

深拷贝 copy.deepcopy()

针对上面对于可变类型,copy.copy()仅仅会拷贝第一层的问题,我们可以使用copy.deepcopy()来进行深度拷贝,进行deepcopy()时,对象内部的引用指向的内存地址也会被拷贝,即会重新创建一份目标对象中的引用指向的内存地址。 来看下面例子:

import copy

a = [1,2,3]
b = [4,5,6]

c = [a,b]

d = c
e = copy.deepcopy(c)

a.append(4)
print(c) # [[1, 2, 3, 4], [4, 5, 6]]
print(e) # [[1, 2, 3], [4, 5, 6]]

# 说明深拷贝deepcopy的时候,如果拷贝的对象内部还接着有引用,那么依次进行内部的拷贝

如果上面例子不够直观,那么可以这么来理解:

import copy

a = [1,2,3]
b = [4,5,6]

c = [a,b]

d = c
e = copy.deepcopy(c)

print( id(c[0]) ) # 140623323590920
print( id(e[0]) ) # 140623323492232
# e的第一个元素的地址,和c第一个元素的地址是不一样的

print( c[0] is a ) # True
print( e[0] is a ) # False
# 意味着e内部将a和b两个变量指向的对象也进行了一份拷贝,而不是跟copy.copy()一样沿用
# c内部的a和b的地址(即只拷贝第一层)

你可能感兴趣的:(Python中的浅拷贝和深拷贝)