python 测试开发面试之深浅拷贝

本贴最后更新于 1724 天前,其中的信息可能已经时移世改

先来道题热热身

a = ('a', 'b','c')
c = copy.copy(a)
d = copy.deepcopy(a)

if c == d:
     print("c和d的值相等")
if id(c) == id(d):
    print("c和d的地址相等")

想想最后打印的是什么?

什么是深拷贝和浅拷贝

深拷贝,就是在对某个对象进行拷贝的时候,如果这个对象持有其他对象的引用,在拷贝的时候会将要拷贝的对象以及引用的对象,一起拷贝。

而浅拷贝只拷贝当前对象和持有的索引,不拷贝索引指向的对象。举个例子说明一下,比如当前有个列表 a = [1,2,3], b = [3,4,a],[3,4,a]对象持有了[1,2,3]对象的引用,在对 b 进行深拷贝的时候,会将 a 对象一起拷贝一份,而浅拷贝的时候则不会。

a = [1,2,3]

b = [4,5,6,a]

对 b 进行浅拷贝

c = copy.copy(b)

这个时候对 a 对象进行修改,会影响 c

a.append(8)
 c
[4, 5, 6, [1, 2, 3, 8]]

对 b 进行深拷贝之后,再对 a 进行修改,则不会影响到 d

d = copy.deepcopy(b)

d
[4, 5, 6, [1, 2, 3, 8]]

a.append(66)

 d
 [4, 5, 6, [1, 2, 3, 8]

当深浅拷贝遇到可变与不可变对象时会发生什么

上面用列表这种可变数据结构举例,再来看一下元组这种不可变结构,在进行深浅拷贝时定的现象。

a = (1,2,3)
b = copy.copy(a)
c = copy.deepcopy(a)
print(id(a))
print(id(b))
print(id(c))

输出:
4502776896
4502776896
4502776896

从结果中发现,a、b、c 的内存地址大都是一样,所以在对不可变对象进行拷贝的时候,无论是浅拷贝还是深拷贝,都没有重新在内存中开辟新的地址,都只是对原对象增加了一个引用。

那如果不可变对象汇总包含有对可变对象的引用又会是怎么样呢?

a1 = [1,2,3]
a = (1,2,3, a1)
b = copy.copy(a)
c = copy.deepcopy(a)
print(id(a))
print(id(b))
print(id(c))

输出:
4502730288
4502730288
4503232240

b 是浅拷贝生成的对象和原对象 a 的内存地址是一样对的,c 是深拷贝生成的对象,发现内存地址和原对象 a 的地址是不一样的。

也就是说如果不可变对象中持有了可变对象的引用,在进行深拷贝的时候会在内存中开辟新的地址存放对象。

回到文章开头提出的问题,是对不可变对象进行拷贝,而且不可变对象中并没有持有可变对象的引用,所以两个 print 语句都会执行。

  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    543 引用 • 672 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...