欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

挖一挖python中的深浅拷贝问题

程序员文章站 2024-01-02 10:51:52
前几天在做面试题的时候,遇到一个与Python深浅拷贝的问题,今天总结出来一个方法,能够快速判断在对一个对象复制后,新对象与原来对象是否会互相影响的方法。 先抛出结论,然后我们对结论进行验证~~~ 先看要被复制的数据类型是否是可变的,我们知道,在Python中: 不可变数据类型:整型,字符串,元组, ......

前几天在做面试题的时候,遇到一个与python深浅拷贝的问题,今天总结出来一个方法,能够快速判断在对一个对象复制后,新对象与原来对象是否会互相影响的方法。

先抛出结论,然后我们对结论进行验证~~~

先看要被复制的数据类型是否是可变的,我们知道,在python中:

不可变数据类型:整型,字符串,元组,

可变数据类型:列表,集合,字典。

 

情况1:如果对整型、字符串和元组类型等不可变数据对象,无论采用=、copy还是deepcopy方法,都相当于是引用了原来对象的内存地址,还是指向了同一块内存。

上代码验证下:

 1 import copy
 2 
 3 a = '哈哈'
 4 #  1、 复制不可变的数据类型
 5 b = a
 6 c = copy.copy(a)
 7 d = copy.deepcopy(a)
 8 #   都是用的同一个内存地址
 9 
10 # print(id(a))  9906224
11 # print(id(b))  9906224
12 # print(id(c))  9906224
13 # print(id(d))  9906224

如上例,我们对字符串a分别进行了3种赋值操作,他们都具有相同的id号,这是浅拷贝。

 

情况2:如果数据类型是诸如列表、字典等可变的数据类型,我们需要看一下数据对象是否包含复杂数据类型,简单来说,是否是列表嵌套列表,字典嵌套字典:

lis1 = [1,2,3,4,5,6]      #简单列表
lis2 = [1,2,3,[4,5,6]]    #包含子列表的复杂列表


dic1 = {'name':'jay','age':18}    #简单字典
dic2 = {'name':'jay','age':18,{'addr':'bj','sex':'famle'}}    #包含子字典的复杂字典
对于深拷贝来说(copy.deepcopy):无论是简单还是复杂的数据结构,二者完全独立,两份互不干扰
import copy

lis = [1,2,[3,4]]
lis1 = copy.deepcopy(lis)
lis1[2][0] = 'ha'
# print(lis1)     # [1, 2, ['ha', 4]]
# print(lis)      # [1, 2, [3, 4]]      #旧列表纹丝未动

对于浅拷贝来说:

简单数据元素如果修改,互不干扰;复杂类型的(嵌套列表、字典)就会互相影响了
import copy

x = [1,2,3,['ahh','lalla']]
y = copy.copy(x)

y[0] = 88
print(x)      # --->  [1, 2, 3, ['ahh', 'lalla']],  列表没有改变

y[3][0] = 'simon'
print(x)     # --->  [1, 2, 3, ['simon', 'lalla']], 列表改变了

 

这是我自己总结的记忆方法:

浅拷贝:分2种情况:
(记忆方法:小明抄小红的作业,小红把最后一个题的答案写在了背面,并注明:答案见背面
小明把前面的作业抄完了,最后也写上了答案见背面,但是小明的试卷后面并没有答案,
所以此时两人的试卷情况:前面的作业互补干扰,是独立的,但是最后一个题的作业用的是同一份)

第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,
同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

第二种情况:复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表),
改变原来的值 中的复杂子对象的值 ,会影响浅复制的值。

 

上一篇:

下一篇: