码迷,mamicode.com
首页 > 其他好文 > 详细

赋值,浅拷贝,深拷贝

时间:2018-11-02 00:11:47      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:color   变量   rom   class   lis   创建   复制   进一步   改变   

一、赋值
str例
a=hello
b=hello
c=a
print(id(a),id(b),id(c))
#2518845789440 2518845789440 2518845789440

我们可以发现a,b,c三者的地址是一样的。所以以上赋值的操作就相当于c=a=b=‘hello‘

赋值是系统先给一个变量或者对象分配了内存,然后再将地址赋给a,b,c。所以它们的地址是相同的

list例

a=[hello]
b=[hello]
c=a
print(id(a),id(b),id(c))
#1924016299912 1924016299976 1924016299912

但是这种情况却不一样了,a和b的地址不同,为什么

因为str是不可变的,所以同样是‘hello’只有一个地址,但是list是可变的,所以必须分配两个地址

 

如果以上两种情况修改了值会怎么样

str例

a=hello
b=hello
c=a
a=world
print(id(a),id(b),id(c))
#2570701091368 2570703634360 2570703634360

这时a的地址和值变量,但是b,c地址和值都未变。因为str的不可变性,a要重新复制则需要重新开辟内存空间,所以a的值改变,a指向的地址改变,b,c由于‘hello’的不可变性,不会发生改变

 

list例

a=[hello]
b=[hello]
c=a
a[0]=world
print(id(a),id(b),id(c))
#2476863774600 2476863774664 2476863774600

这时a,c的值和地址均改变,但二者仍相同,b不改变,由于list的可变性,所以修改list的值不需要另外开辟空间,只需修改原地址的值,所以a,c均改变

 

二、浅拷贝

1 a=[hello,[123,234]]
2 b=a[:]
3 print(id(a),id(b))
4 print(id(a[0]),id(a[1]))
5 print(id(b[0]),id(b[1]))
6 
7 #2142142193608 2142142197896
8 #2142022964480 2142142193544
9 #2142022964480 2142142193544

我们可以看出a,b地址不同,这符合list是可变的,应开辟不同的空间,我们看第四行和第五行,发现元素的地址也是相同的。如果说字符串‘hello’地址一致还能理解,但是第二个元素的list地址仍一致。这就说明了浅拷贝的特点,只是将容器内的元素的地址复制了一份

接着我们尝试修改a,b中的值

a=[hello,[123,234]]
b=a[:]

a[0]=world
a[1].append(345)
print(a)
print(b)

#[‘world‘, [123, 234, 345]]
#[‘hello‘, [123, 234, 345]]

a中第一个元素str改变,但是b中未改变,a中第二个元素改变,b中也改变,这就符合不可变的对象修改会开辟新的空间,可变的对象修改不会开辟新空间,也进一步证明了浅拷贝仅仅是复制了容器中元素的地址

三、深拷贝

from copy import deepcopy
a=[hello,[123,234]]
b=deepcopy(a)
print(id(a),id(b))
print(id(a[0]),id(a[1]))
print(id(b[0]),id(b[1]))

#2576042483656 2576042487944
#2575924887480 2576042483592
#2575924887480 2576042488136

深拷贝后,可以发现a,b地址以及a,b中元素地址均不同。这才是完全拷贝了一个副本

1 from copy import deepcopy
2 a=[hello,[123,234]]
3 b=deepcopy(a)
4 
5 a[0]=world
6 a[1].append(345)
7 print(a)
8 print(b)

#[‘world‘, [123, 234, 345]]
#[‘hello‘, [123, 234]]

从打印结果来看仅仅a修改了,b没有任何修改。因为b是一个完全的副本,元素地址均与a不同,a修改,b不受影响

 

总结

1、赋值是将一个对象的地址赋值给一个变量,让变量指向改地址

2、浅拷贝是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是原对象的元素的地址的拷贝,也就是说新的容器中指向了旧的元素

3、深拷贝是在另一块地址中创建一个新的变量或容器,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本

 

赋值,浅拷贝,深拷贝

标签:color   变量   rom   class   lis   创建   复制   进一步   改变   

原文地址:https://www.cnblogs.com/z-x-y/p/9893084.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!