Python基础【3】:Python中的深浅拷贝解析
深浅拷贝
在研究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 #当有多层镶套时,源对象改变后,浅拷贝和共享引用的值都变了,而深拷贝没有变。

【总结】
深浅拷贝都是对源对象的复制,占用不同的内存空间
如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
序列对象的切片其实是浅拷贝,即只拷贝顶级的对象
Python基础【3】:Python中的深浅拷贝解析的更多相关文章
- python基础知识5——赋值与深浅拷贝——整数和字符串,列表元组字典
深浅copy 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. 1 import copy 2 # ######### 数字.字符串 #### ...
- Core Python Programming一书中关于深浅拷贝的错误
该书关于深浅拷贝的论述: 6.20. *Copying Python Objects and Shallow and Deep Copies "when shallow copies are ...
- python基础-3 集合 三元运算 深浅拷贝 函数 Python作用域
上节课总结 1 运算符 in 字符串 判断 : “hello” in "asdasfhelloasdfsadf" 列表元素判断:"li" in ['li', ...
- 天啦噜!仅仅5张图,彻底搞懂Python中的深浅拷贝
Python中的深浅拷贝 在讲深浅拷贝之前,我们先重温一下 is 和==的区别. 在判断对象是否相等比较的时候我们可以用is 和 == is:比较两个对象的引用是否相同,即 它们的id 是否一样 == ...
- Python 中的深浅拷贝
Python 中的深浅拷贝 参考文献:https://blog.csdn.net/lnotime/article/details/81194633 参考文献:https://blog.csdn.net ...
- 二十一. Python基础(21)--Python基础(21)
二十一. Python基础(21)--Python基础(21) 1 ● 类的命名空间 #对于类的静态属性: #类.属性: 调用的就是类中的属性 #对象.属性: 先从自己的内存空间里找名 ...
- js中的深浅拷贝
js中的深浅拷贝 js中有深拷贝.浅拷贝一说,所谓的深浅拷贝是针对value类型为引用类型(函数.对象.数组)而言的,大概理解的就是: 浅拷贝: 拷贝出的对象c和原始对象o,c和o在key对应的val ...
- Python中的深浅拷贝
1.什么是深浅拷贝? python中一切皆对象,python中的数字.字符串.元组等,如果存放在了内存中,这部分内存里面的内容是不会改变的,但是也有情况,内存中存放了可变对象,比如说列表和字典,他们的 ...
- Python中的深浅拷贝,赋值及引用
简单来说,若对象a中存的是列表或字典等可变对象,b对a的浅拷贝只是对对象第一层的复制,修改b第二层的元素仍然会影响两个对象. 深拷贝则是不会影响原来的对象. import copy.copy() 浅拷 ...
随机推荐
- 2_C语言中的数据类型 (九)逻辑运算符与if语句、switch、条件运算符?、goto语句与标号
1 条件分支语句 1.1 关系运算符 在C语言中0代表false,非0代表真 1.1.1 < 小于 1.1.2 <= 小于 ...
- P4249 [WC2007]剪刀石头布
有一个竞赛图,要给一些边定向,求三元环最多的数量 反过来考虑最少的不是环的三个点(称为不好的环),一定有一个点有2条入边,一个点有2条出边,一个点1入边1出边 可以对每一个不好的环只记录入边为2的点, ...
- 解决 java循环中使用 Map时 在put值时value值被覆盖的问题
其实很简单,只需要把容器换成list 然后在循环中,每次循环末尾map = new HashMap() 或者直接在循环中一开始就实例化hashmap(Map map = new HashMap();) ...
- 我在华为,软件测试人员在工作中如何运用Linux?
从事过软件测试的小伙们就会明白会使用Linux是多么重要的一件事,工作时需要用到,面试时会被问到,简历中需要写到.对于软件测试人员来说,不需要你多么熟练使用Linux所有命令,也不需要你对Linux系 ...
- 二、Unity Editor模式下,操作选中对象
使用Unity提供的工具类 UnityEditor.Selection public static GameObject activeGameObject public static UnityEng ...
- Azure-如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(二)
问题描述 经过如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(一)中的排查步骤,可以判断出是由于 Web 服务器自身问题导致的响应异常. 那么可以在 IIS ...
- 记录一次redis故障
ResponseError: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persi ...
- dubbo支持协议及具体对比
对dubbo的协议的学习,可以知道目前主流RPC通信大概是什么情况,本文参考dubbo官方文档 http://dubbo.io/User+Guide-zh.htm dubbo共支持如下几种通信协议: ...
- centos下配置gitosis服务器
背景: 一台windows电脑,Xshell可以登录centos服务器(centos7.2 64位,有root用户权限),windows电脑已经安装好git和tortoies 在windows下下载和 ...
- 第十次PSP