深浅拷贝

在研究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中的深浅拷贝解析的更多相关文章

  1. python基础知识5——赋值与深浅拷贝——整数和字符串,列表元组字典

    深浅copy 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. 1 import copy 2 # ######### 数字.字符串 #### ...

  2. Core Python Programming一书中关于深浅拷贝的错误

    该书关于深浅拷贝的论述: 6.20. *Copying Python Objects and Shallow and Deep Copies "when shallow copies are ...

  3. python基础-3 集合 三元运算 深浅拷贝 函数 Python作用域

    上节课总结 1 运算符 in 字符串 判断  : “hello” in "asdasfhelloasdfsadf" 列表元素判断:"li" in ['li', ...

  4. 天啦噜!仅仅5张图,彻底搞懂Python中的深浅拷贝

    Python中的深浅拷贝 在讲深浅拷贝之前,我们先重温一下 is 和==的区别. 在判断对象是否相等比较的时候我们可以用is 和 == is:比较两个对象的引用是否相同,即 它们的id 是否一样 == ...

  5. Python 中的深浅拷贝

    Python 中的深浅拷贝 参考文献:https://blog.csdn.net/lnotime/article/details/81194633 参考文献:https://blog.csdn.net ...

  6. 二十一. Python基础(21)--Python基础(21)

    二十一. Python基础(21)--Python基础(21) 1 ● 类的命名空间 #对于类的静态属性:     #类.属性: 调用的就是类中的属性     #对象.属性: 先从自己的内存空间里找名 ...

  7. js中的深浅拷贝

    js中的深浅拷贝 js中有深拷贝.浅拷贝一说,所谓的深浅拷贝是针对value类型为引用类型(函数.对象.数组)而言的,大概理解的就是: 浅拷贝: 拷贝出的对象c和原始对象o,c和o在key对应的val ...

  8. Python中的深浅拷贝

    1.什么是深浅拷贝? python中一切皆对象,python中的数字.字符串.元组等,如果存放在了内存中,这部分内存里面的内容是不会改变的,但是也有情况,内存中存放了可变对象,比如说列表和字典,他们的 ...

  9. Python中的深浅拷贝,赋值及引用

    简单来说,若对象a中存的是列表或字典等可变对象,b对a的浅拷贝只是对对象第一层的复制,修改b第二层的元素仍然会影响两个对象. 深拷贝则是不会影响原来的对象. import copy.copy() 浅拷 ...

随机推荐

  1. 负载均衡@StackExchange.Redis实现Session外置--纯干货喂饱你

    Redis和StackExchange.Redis redis有多个数据库1.redis 中的每一个数据库,都由一个 redisDb 的结构存储.其中,redisDb.id 存储着 redis 数据库 ...

  2. express的web server设置流程

    对于express的设置,一直是拿来就用,只知其然,今天查了一下文档,记录详细过程如下. 1.实现基本常用功能需要的模块path 用来处理路径字符串拼接,设置模板路径和静态资源路径时使用cookie- ...

  3. fiddler和bugfree之间的联动(做伪请求、伪响应、并发、抓密码)

    青.取之于蓝,而青于蓝:冰.水为之,而寒于水 不积跬步,无以至千里;不积小流,无以成江海. 1解压Fiddler Web Debugger V4.6.2017修正中文第6版至C盘Program Fil ...

  4. C语言操作符学习总结

    c语言中关于操作符部分的学习,可以主要分为两个部分:操作符和表达式. 这里首先是列举各种操作符,在C语言中,一般主要的操作符有这么几种:算数操作符,移位操作符,位操作符,赋值操作符,单目运算符,关系操 ...

  5. PHP核心技术——异常和错误处理

    PHP只有手动抛出异常后才能捕获异常 $a = null; try { $a = 5/0; echo $a,PHP_EOL; } catch (exception $e) { $e -> get ...

  6. Centos7 安装与破解 Confluence 6.7.1

    1.1硬件需求建议: CPU:32/64 bit 2.27GHz双核心以上之CPU: 内存:8GB以上: 硬盘:300GB,7200转以上: 建议数据库.Confluence等各自独立一台服务器(本测 ...

  7. ats Linux Bridge内联

    Linux可以配置为在桥接模式下运行. 为网桥分配了两个或更多物理接口. 在接口之间共享单个IP地址. 默认情况下,任何到达一个接口的数据包都会立即路由到另一个网桥接口. 需要的Linux包: bri ...

  8. Ansible 连接主机显示报错的处理方案

    一.在ansible安装完毕后一般需要以SSH的方式连接到需要进行管理的目标主机,一开始遇到了如下问题: 192.168.15.4 | UNREACHABLE! => {    "ch ...

  9. 铁轨(rails, ACM/ICPC CERC 1997,Uva 514)

    铁轨(rails, ACM/ICPC CERC 1997,Uva 514) 题目描述 某城市有一个火车站,铁轨铺设如图所示.有n节车厢从A方向驶入车站,按进站顺序编号为1~n.你的任务是让它们按照某种 ...

  10. 利用Cocoapods创建基于SVN的私有库podspec

    由于项目年后要进行组件化,考虑到公司内部实现的一些私有组件,不对外公开,而又想在不同项目中使用,该怎么办呢?由于cocoapods有了强大的功能,可以自己创建podspec,更可以设置私有的库.那么利 ...