深浅拷贝

发布时间 2023-08-30 00:09:34作者: Allen_Hao

普通赋值

 1 # 1 普通赋值
 2 a = [1, 2, 3]
 3 b = [11, 22, 33]
 4 c = [a, b]
 5 
 6 d = c
 7 
 8 print(id(d))  # 2517490235456
 9 print(id(c))  # 2517490235456
10 print(f"c={c}")  # c=[[1, 2, 3], [11, 22, 33]]
11 print(f"d={d}")  # d=[[1, 2, 3], [11, 22, 33]]
12 print(id(c[1]))  # 1234100025024
13 print(id(d[1]))  # 1234100025024
14 
15 '''
16 普通的赋值就是引用的拷贝。就像windows快捷键一样,本质上指向的同一个东东
17 '''

 

浅拷贝(shallow copy)

浅拷贝可变类型

 1 import copy  # 1. 导入copy模块
 2 # 2 浅拷贝可变类型
 3 a = [1, 2, 3]
 4 b = [11, 22, 33]
 5 c = [a, b]
 6 
 7 d = copy.copy(c)  # 2. 进行浅拷贝
 8 
 9 print(id(d))  # 2260319076224
10 print(id(c))  # 2493865459584
11 
12 '''
13 浅拷贝就是可变类型操作,就是创建开辟一个新空间,存储拷贝对象
14 '''

 

浅拷贝深层可变类型

 

 1 import copy  # 1. 导入浅拷贝模块
 2 
 3 #  浅拷贝-可变类型-深层数据
 4 a = [1, 2, 3]
 5 b = [11, 22, 33]
 6 c = [a, b]
 7 
 8 d = copy.copy(c)  # 2. 对深层数据-可变类型进行浅拷贝
 9 
10 #  都是执行a列表
11 print(id(a))     # 1890180887936
12 print(id(c[0]))  # 1890180887936
13 print(id(d[0]))  # 1890180887936

说明前拷贝对可变类型拷贝,只拷贝了一层。

浅拷贝不可变类型

 1 import copy
 2 
 3 # 浅拷贝不可变类型
 4 a = (1, 2, 3)
 5 b = (11, 22, 33)
 6 c = (a, b)
 7 
 8 d = copy.copy(c)
 9 
10 print(id(d))  # 1565409147712
11 print(id(c))  # 1565409147712
12 '''
13 对不可变类型进行浅拷贝,只是拷贝了引用
14 '''

深拷贝(deep copy)

深拷贝可变类型

 1 import copy
 2 
 3 # 深拷贝可变类型
 4 a = [1, 2, 3]
 5 b = [11, 22, 33]
 6 c = [a, b]
 7 
 8 d = copy.deepcopy(c)
 9 
10 print(id(c))  # 2384833019136
11 print(id(d))  # 2384833019776
12 
13 print(id(c[0]))  # 2384832984448
14 print(id(d[0]))  # 2384833043264
15 
16 '''
17 对可变类型的每一层可变类型都拷贝了一份
18 '''

深拷贝-深层数据的可变类型

 1 import copy
 2 
 3 # 深拷贝-深层数据
 4 a = [1, 2, 3]
 5 b = [11, 22, 33]
 6 c = [a, b]  # 此处是拷贝了引用
 7 
 8 d = copy.deepcopy(c)
 9 
10 print(id(a))          # 1490657047936
11 print(id(c[0]))      # 1490657047936
12 print(id(d[0]))     # 1490657106752 变化了

深拷贝-拷贝不可变类型

 1 import copy
 2 
 3 # 深拷贝不可变类型
 4 a = (1, 2, 3)
 5 b = (11, 22, 33)
 6 c = (a, b)
 7 
 8 d = copy.deepcopy(c)
 9 
10 print(id(c))  # 2367734086464
11 print(id(d))  # 2367734086464
12 
13 '''
14 深拷贝对不可变类型只是拷贝引用
15 '''

 

总结

 

 

1. 思考下面的代码运行出的结果是什么:
    list = [0, 1, 2]
    list[1] = list
    print(list)
	
	
参考答案:
	[0, [...], 2]
    list的第2个元素指向list本身, 所以无限循环
    
2. 如何得出list = [0, [0, 1, 2], 2]这样的结果?

参考答案:
    list[1] = list[:] 
	列表的切片其实是浅拷贝
	


3. 经过以下步骤, a和b分别是多少? 为什么? 
    a = [0, [1, 2], 3]
    
    b = a[:]
    a[0] = 8
    a[1][1] = 9
    
参考答案:

a = [8, [1, 9], 3]
b = [0, [1, 9], 3]

a[:]是浅拷贝, 只对对象最顶层进行拷贝
    
4. 如何保证第3题中最终b = [0, [1, 2], 3]

参考答案: 使用深拷贝


5. 写出下面代码执行结果:
    L = [1, 2]
    M = L
    L = L + [3, 4]
    print(L)
    print(M)
    
    
6. 写出下面代码执行结果:
    L = [1, 2]
    M = L
    L += [3, 4]
    print(L)
    print(M)
    
   L += [3, 4]  是L本身加上[3, 4]
   
   L = L + [3, 4] 先计算等号右边, 得到一个新的引用, 指向新的L(等号右边的L是原来的L, 等号左边的是一个新的L)

    
7. 执行以下代码:

def foo(a, b, c=[]):
    c.append(a)
    c.append(b)
    print(c)

foo(1, 2)   python解释器没有接收到c的参数, 使用默认的空列表(缺省参数)

foo(1, 2, [])   python解释器接收到新的c的参数, 就是用新的空列表, 此时, 缺省参数的列表已经变为[1, 2]

foo(3, 4)   python解释器没有接收到c的参数, 继续使用默认的缺省列表, 即[1, 2].append[3, 4]