普通赋值
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]