深浅拷贝

在研究Python的深浅拷贝区别前需要先弄清楚以下的一些基础概念:

变量--引用--对象(可变对象,不可变对象)

切片(序列化对象)--拷贝(深拷贝,浅拷贝)

我是铺垫~

一、【变量--引用--对象】:

Python中一切皆对象,甚至连type本身都是type对象。

  1 >>> type(type(n1))
2 <class 'type'>

Python中的变量不同于与Java/c/c++不同,它是对象的引用,是动态型变量,数据类型无须提前声明,变量类型是根据对象的类型动态变化。

例如运行n=9,Python内部先在内存中找块地址来存储9,n只是对这个对象的引用,或者说将指针指向这个对象。

这里的整数对象9包含了两层含义:

1、数值为9

2、一个头部信息,告诉Python这是个int对象【可理解为一个指向int类型的指针】

小结:

变量是一个系统表的元素,拥有指向对象的连接的空间;

对象是被分配的一块内存,用来存储值;

引用是在变量赋值时自动形成的变量到对象的指针。

再来看下面的例子:

  1 >>> a = 3
2 >>> b = a
3 >>> id(a);id(b)
4 1627390480
5 1627390480
6 >>> del a
7 >>> b
8 3 >>> a = 5 >>> b 3

可以看出,a和b共享引用,指向同一个内存地址(其id完全相同),所以将变量a删除或者将a赋值为4,都对变量b的数值无影响。

上面的例子有一个局限,就是数值类型对象是不可改变的,如果换成列表和元组对象呢?

二、【可变对象--不可变对象】

Python中的可变对象:可以修改的对象,列表和字典。

Python中的不可变对象:一旦创建就不可以修改的对象,字符串、元组、整数。

  1 >>> L1 = [2,3,4]
2 >>> L2 = L1
3 >>> L2
4 [2, 3, 4]
5 >>> L1= [5,6]
6 >>> L2
7 [2, 3, 4]
8 >>> L1 = [1,2,3]
9 >>> L2 = L1
10 >>> L1[0] = 99
11 >>> L1;L2
12 [99, 2, 3]
13 [99, 2, 3]
14 #因为对象本身变了

如此一来,可变对象的变量共享引用就可能会有问题了(原本对源变量的修改,一不小心影响了其他的变量引用)。所以针对这种情景,才有了深浅copy。

那么如果不想改变上面L2的值有两种作法:切片和copy模块。

  1 >>> L1
2 [99, 2, 3]
3 >>> L2 = L1[:]
4 >>> L1,L2
5 ([99, 2, 3], [99, 2, 3])
6 >>> id(L1);id(L2)
7 3089554433480
8 3089554433992
9 >>> L1[0] = 100
10 >>> L1;L2
11 [100, 2, 3]
12 [99, 2, 3]

拷贝

切片技术的应用范围:序列对象,即列表、字符串、元组。

注:序列是一类基本数据类型(字符串/列表/元组)的统称,这些数据类型都含有一些共同的特性。

切片不能应用于字典,对于字典只有dic.copy()方法和dic.deepcopy()方法。

  1 >>> dic = {'name':'bolen','age':18}
2 >>> [item for item in dir(dic) if not item.startswith('__')]
3 ['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
4
5 #上面的语法和三元运算一样,x = 1 if n >2 else 3(或x = [2,1][n>2]),都是Python中的语法糖。
  1 >>> import copy
2 >>> L3 = copy.copy(L1)
3 >>> L4 = copy.deepcopy(L1)
4 >>>

上面铺垫了这么多,就是想说深浅拷贝,既可应用于序列对象也可用于字典。

【浅拷贝】

浅拷贝只拷贝顶层对象或者说父级对象。

【深拷贝】

深拷贝是拷贝所有对象,包括顶级对象和镶套对象,或者说拷贝所有父对象和子对象。

闲言少叙,show code:

  1 >>> n1
2 {'k1': 'lilei', 'k3': ['yy', 456], 'k2': 123}
3 >>> n4 = n1
4 >>> n2= copy.copy(n1)
5 >>> n3 = copy.deepcopy(n1)
6 >>> n1;n2;n3;n4
7 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
8 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
9 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
10 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
11 >>> id(n1);id(n2);id(n3);id(n4)
12 3089553992072
13 3089554432904
14 3089554359368
15 3089553992072
16 #深浅拷贝内存地址和源对象都不一样。
17 >>> n1['k1'] = 'bolen'
18 >>> n1;n2;n3;n4
19 {'k1': 'bolen', 'k3': ['yy', 456], 'k2': 123}
20 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
21 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
22 {'k1': 'bolen', 'k3': ['yy', 456], 'k2': 123}
23 >>> n1['k3'][1]=789
24 >>> n1;n2;n3;n4
25 {'k1': 'bolen', 'k3': ['yy', 789], 'k2': 123}
26 {'k1': 'bboo', 'k3': ['yy', 789], 'k2': 123}
27 {'k1': 'bboo', 'k3': ['yy', 456], 'k2': 123}
28 {'k1': 'bolen', 'k3': ['yy', 789], 'k2': 123}
29 #当有多层镶套时,源对象改变后,浅拷贝和共享引用的值都变了,而深拷贝没有变。

【总结】

深浅拷贝都是对源对象的复制,占用不同的内存空间
如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
序列对象的切片其实是浅拷贝,即只拷贝顶级的对象

最新文章

  1. MyBatis2:config.xml文件
  2. &lt;Script&gt;放置位置
  3. 去掉tableview顶部留白
  4. 一次进程hang住问题分析。。。
  5. mysql——查询练习
  6. 使用Gradle自动发布Java Web到SAE
  7. pycharm常用快捷键
  8. SQL 常用方法
  9. CICS中设置程序常驻内存
  10. Nginx高性能服务器安装、配置、运维 (5) —— Nginx虚拟主机配置
  11. 奔五的人,准备学习iOS开发
  12. mysql 准则 杂谈
  13. C语言之运算符和条件结构
  14. 重温Android中的消息机制
  15. IDEA 创建Web项目
  16. 10.TreeSet、比较器
  17. day043 前端css样式
  18. Codeforces Round #394 (Div. 2) A,B,C,D,E
  19. ref:JAVA代码审计的一些Tips(附脚本)
  20. 15、xtrabackup 全量备份

热门文章

  1. 4827: [Hnoi2017]礼物
  2. 关于Mybatis的Example(and ,or )应用
  3. Python面向过程、模块的使用
  4. python的super函数学习
  5. 【免费培训】腾讯WeTest&amp;TesterHome WorkShop | 一起学压测
  6. Springboot日记——核心编码篇
  7. 发现一个很N且免费的html5拓扑图 关系图 生成组件
  8. 【原创】MVC项目中使用JQuery的upladify图片上传插件相关问题的解决方案
  9. 如何获取c:forEach里面点击时候的值
  10. 32bit GM命令