浅谈深浅拷贝

 

所谓深浅拷贝,一深一浅嘛

 

说白了,就是一个深拷贝和一个浅拷贝

 

 注释:以下观点纯属个人瞎扯,欢迎提出辩驳,共同探讨

深拷贝

先来说最简单的深拷贝

什么是深拷贝呢?先来看一段代码

 1 import copy
 2 
 3 # 首先创建一个变量
 4 s1 = ['Nathaniel','python',(1,2,3,4),False]
 5 # 然后进行深拷贝,  deep就是深的意思嘛
 6 s2 = copy.deepcopy(s1)# 深拷贝s1的值赋给s2
 7 
 8 # 打印s1和s2的id
 9 print(id(s1))
10 print(id(s2))

执行上述代码可以发现 , s1和s2的内存地址是不同的(当然每次执行打印的值也有可能不同,但是s1和s2的值是一直不同的)

这就是深拷贝,炒鸡简单,相当于s2完全复制s1,是一个完全独立的新个体,从此再和s1没有一毛钱关系了

1 s2[0] = 'miracle'
2 print(s1)
3 s2[3] = 2017
4 print(s1)

上述代码对s2进行各种修改,但s1始终岿然不动,就是因为s1和s2是两个完全不同的独立个体

 

浅拷贝

在弄清浅拷贝之前先来看这样一段代码,相信不少同学在学习浅拷贝的时候都会产生疑惑

1 s1 = 1
2 s2 = s1
3 print(id(s1))
4 print(id(s2))

执行的时候你会发现打印出来的值是相同的

也就是说刚建立s1的时候,分配了一个内存地址给s1,然后又建立了一个变量s2,s2是等于s1的

这时候实际上做的是什么事情呢?很简单,其实只是将s2的指针也就是s2内存地址指向了s1的内存地址,s2这个时候可以理解为s1的一个别名,上图

相当于值1有两个门牌号,根据这个门牌号就找到了存在内存中的1

这时候对s1进行一些操作,比如

1 s1 = 2
2 if s2 == s1:
3     print(233)

那么问题来了,将s1的值修改之后,s1还等于s2么?我们加入以上代码,执行,发现,233并没有被打印出来,说明此时,s1不等于s2了,继续加代码,看看这个时候s1和s2的内存地址

 1 s1 = 1
 2 s2 = s1
 3 print(id(s1))
 4 print(id(s2))
 5 s1 = 2
 6 if s2 == s1:
 7     print(233)
 8 
 9 print(id(s1))
10 print(id(s2))

我们发现,在第五行代码执行之前,s1和s2的内存地址是一样的,但是,我们将s1重新赋值之后,s2的内存地址没有变化,但是s1的内存地址变化了   上图

这张图就能很好解释为什么对s1重新赋值之后s2不再等于s1了

因为初始状态s2是直接指向s1的内存地址,所以s1和s2本质上是没什么区别的

当我们修改了s1的时候,s1的内存指向发生了变化,而s2没有变化,所以s1不再等于s2了

 

 

可是!这不是浅拷贝啊,那我讲这个的意义何在呢?

看这样一段代码,先别执行,想一下,这段代码执行会是什么结果

1 import copy
2 s1 = ['Nathaniel','python',[1,2,3,4],False]
3 s2 = copy.copy(s1)
4 s1[2][0] = 'alex'
5 print(s1)
6 print(s2)

 

 

 

看完了吗?试想一下执行这段代码应当是什么结果呢?按照之前说的,s2直接指向s1的内存地址,我们对s1进行了修改,并没有改s2,所以s2打印出来应当还是  ['Nathaniel','python',[1,2,3,4],False]

真的是这样吗?执行一下看看

哈哈哈哈哈哈,是不是大失所望呢?

but why?

别着急,上图

 

也就是说,表面上我们修改了s1的值,实际上s1所指向的内存地址并没有发生变化,所以s2与s1仍旧指向同一个内存地址,所发生变化的只是[1,2,3,4]这个列表里边的某一个元素的内存地址,而列表本身的内存地址并没有发生变化

 

再看

1 import copy
2 s1 = ['Nathaniel','python',[1,2,3,4],False]
3 s2 = copy.copy(s1)
4 s1[0] = 'alex'
5 print(s1)
6 print(s2)

打印一下,是什么结果呢?

s1和s2是不是不一样了呢?

but why?

明明同样是创建s1,然后浅拷贝赋值给s2,然后修改s1,再分别打印s1和s2,为什么结果截然不同呢?

别急,回头多看几遍,根据内存地址,仔细思考一下

如果还是无法理解,那就只能这样了

怎样呢?记住,浅拷贝只会拷贝第一层,浅拷贝只会拷贝第一层,浅拷贝只会拷贝第一层!

 

测试:

 1 import copy
 2 s1 = 1
 3 s2 = s1
 4 s1 = 2
 5 if s2 == s1:
 6     print(233)
 7 
 8 s1 = ['Nathaniel','python',(1,2,3,4),False]
 9 s2 = s1
10 if s2 == s1:
11     print(233)
12 
13 s1 = ['Nathaniel','python',(1,2,3,4),False]
14 s2 = copy.copy(s1)
15 s2[0] = 'alex'
16 if s2 == s1:
17     print(233)
18 
19 s1 = ['Nathaniel','python',[1,2,3,4],False]
20 s2 = copy.copy(s1)
21 s2[2][2] = 'alex'
22 if s2 == s1:
23     print(233)

问,上述代码共会打印几个233呢?

 

 

a = 1
def func(a):
    a = 2
func(a)
print(a)


b = []
def func1(a):
    a.append(1)
func1(b)
print(b)
思考🤔

 

posted @ 2017-10-10 11:17  Nathaniel-J  阅读(227)  评论(0编辑  收藏  举报