python赋值、浅拷贝和深拷贝

概述

此概念容易在面试笔试中问到

本文针对的数据类型是list、set、dict等可变数据类型,其他数据类型在本文中意义不大

赋值

观察且执行下面代码:

l=[1,2,3]
l2=l
l.append(4)
print(id(l))
print(id(l2))
print(l)
print(l2)

结果如下:

50178288
50178288
[1, 2, 3, 4]
[1, 2, 3, 4]

像l2=l这种直接赋值,l和l2的引用指向 同一个内存地址,所以当改变l的值,l2也跟着改变

copy浅拷贝

观察且执行下面代码

import copy
l=[1,3.14,[2,4,6]]
l2=copy.copy(l)

print(l)
print(l2)

print(id(l))
print(id(l2))

结果如下:

[1, 3.14, [2, 4, 6]]
[1, 3.14, [2, 4, 6]]
8563088
8580432

执行代码l2=copy.copy(l)后,两个变量的 内容一样,但是两个变量的引用指向 不同的地址

继续编码,并观察执行结果

l.append('python')
print(l)
print(l2)

结果如下:

[1, 3.14, [2, 4, 6], 'python']
[1, 3.14, [2, 4, 6]]

因为两个变量的引用指向 不同的地址,所以一个list追加元素,另一个list不会改变

list内元素的地址

继续编码,分别查看每个list的元素的地址

for item in l:
    print(id(item),end=',')
print()
for item in l2:
    print(id(item),end=',')

执行结果如下:

1616306960,52857232,52865544,
1616306960,52857232,52865544,

两个list内的元素地址相同

继续编码,并观察执行结果

l[2].append(8)

print(l)
print(l2)

打印的结果是否相同

总结

copy浅拷贝的特点:

  1. 浅拷贝后,两个序列的 内存地址 不同
  2. 两个序列 相同索引 的 元素 的 内存地址 相同

深拷贝

观察且执行下面代码

import copy
l=[1,3.14,[2,4,6],'python']
l2=copy.deepcopy(l)

print(l)
print(l2)

print(id(l))
print(id(l2))

结果如下:

[1, 3.14, [2, 4, 6], 'python']
[1, 3.14, [2, 4, 6], 'python']
9087376
9104920

执行代码l2=copy.deepcopy(l)后,两个变量的 内容一样,但是两个变量的引用指向 不同的地址

继续编码,并观察执行结果

l.append('深拷贝')
print(l)
print(l2)

结果如下:

[1, 3.14, [2, 4, 6], 'python','深拷贝']
[1, 3.14, [2, 4, 6], 'python']

因为两个变量的引用指向 不同的地址,所以一个list追加元素,另一个list不会改变

list内元素的地址

观察执行下面的代码,深拷贝后,分别打印每个list内元素的地址

l=[1,3.14,'python',(1,2),[2,4,6],{3,4,5}]
l2=copy.deepcopy(l)
for item in l:
    print(id(item),end=',')
print()
for item in l2:
    print(id(item),end=',')

执行结果如下:

1616306960,52595088,52109792,52620864,52603400,52607616,
1616306960,52595088,52109792,52620864,52621144,52607856,

两个list内的元素 地址:

  1. 如果元素是数字、字符串、tuple等 不可变数据类型,地址相同
  2. 如果元素是list、set等 可变数据类型,地址不同

继续编码,并观察执行结果

l[2].append(8)

print(l)
print(l2)

打印的结果是否相同

总结

copy深拷贝的特点:

  1. 深拷贝的两个序列的 内存地址 不同
  2. 如果内部元素是 int、float、str、bool、tuple 等 不可变数据类型,内存地址 相同
  3. 如果内部元素是 list、set、dict 等 可变数据类型,内存地址 不同

原文出处:/show_1EF2wnK1OSYv.html