python赋值、浅拷贝、深拷贝区别
在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出现一些问题。所以,在这里按个人的理解谈谈它们之间的区别。
一、赋值(assignment)
在《Python FAQ1》一文中,对赋值已经讲的很清楚了,关键要理解变量与对象的关系。
>>> a = [1, 2, 3]
>>> b = a
>>> print(id(a), id(b), sep='\n')
139701469405552
139701469405552
在Python中,用一个变量给另一个变量赋值,其实就是给当前内存中的对象增加一个“标签”而已。
如上例,通过使用内置函数 id() ,可以看出 a 和 b 指向内存中同一个对象。a is b会返回 True 。
二、浅拷贝(shallow copy)
注意:浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。
所谓“浅拷贝”,是指创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)
常见的浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。
>>> a = [1, 2, 3]
>>> b = list(a)
>>> print(id(a), id(b)) # a和b身份不同
140601785066200 140601784764968
>>> for x, y in zip(a, b): # 但它们包含的子对象身份相同
... print(id(x), id(y))
...
140601911441984 140601911441984
140601911442016 140601911442016
140601911442048 140601911442048
从上面可以明显的看出来,a 浅拷贝得到 b,a 和 b 指向内存中不同的 list 对象,但它们的元素却指向相同的 int 对象。这就是浅拷贝!
三、深拷贝(deep copy)
所谓“深拷贝”,是指创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。
深拷贝只有一种方式:copy模块中的deepcopy函数。
>>> import copy
>>> a = [1, 2, 3]
>>> b = copy.deepcopy(a)
>>> print(id(a), id(b))
140601785065840 140601785066200
>>> for x, y in zip(a, b):
... print(id(x), id(y))
...
140601911441984 140601911441984
140601911442016 140601911442016
140601911442048 140601911442048
看了上面的例子,有人可能会疑惑:
为什么使用了深拷贝,a和b中元素的id还是一样呢?
答:这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用。而且这种机制并不会影响 a 和 b 的相互独立性,因为当两个元素指向同一个不可变对象时,对其中一个赋值不会影响另外一个。
我们可以用一个包含可变对象的列表来确切地展示“浅拷贝”与“深拷贝”的区别:
>>> import copy
>>> a = [[1, 2],[5, 6], [8, 9]]
>>> b = copy.copy(a) # 浅拷贝得到b
>>> c = copy.deepcopy(a) # 深拷贝得到c
>>> print(id(a), id(b)) # a 和 b 不同
139832578518984 139832578335520
>>> for x, y in zip(a, b): # a 和 b 的子对象相同
... print(id(x), id(y))
...
139832578622816 139832578622816
139832578622672 139832578622672
139832578623104 139832578623104
>>> print(id(a), id(c)) # a 和 c 不同
139832578518984 139832578622456
>>> for x, y in zip(a, c): # a 和 c 的子对象也不同
... print(id(x), id(y))
...
139832578622816 139832578621520
139832578622672 139832578518912
139832578623104 139832578623392
从这个例子中可以清晰地看出浅拷贝与深拷贝地区别。
总结:
1、赋值:简单地拷贝对象的引用,两个对象的id相同。
2、浅拷贝:创建一个新的组合对象,这个新对象与原对象共享内存中的子对象。
3、深拷贝:创建一个新的组合对象,同时递归地拷贝所有子对象,新的组合对象与原对象没有任何关联。虽然实际上会共享不可变的子对象,但不影响它们的相互独立性。
浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。
python赋值、浅拷贝、深拷贝区别的更多相关文章
- python赋值,深拷贝和浅拷贝的区别
1.赋值 list1=[[1,2],'fei',66] list2=list1 list1 [[1, 2], 'fei', 66] list2 [[1, 2], 'fei', 66] list2.ap ...
- python中赋值-浅拷贝-深拷贝之间的关系
赋值: 变量的引用,没有拷贝空间 对象之间赋值本质上 是对象之间的引用传递而已.也就是多个对象指向同一个数据空间. 拷贝的对象分两种类型: . 拷贝可变类型 浅拷贝: 只拷贝第一层数据,不关心里面的第 ...
- python 中的 赋值 浅拷贝 深拷贝
1.对象的赋值 都是进行对象引用(内存地址)传递,即 b is a ,a 变 b也变 2.浅拷贝 会创建一个新的对象,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址) 当我们使用下面的操作 ...
- 搞不懂JS中赋值·浅拷贝·深拷贝的请看这里
前言 百科定义:拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这 ...
- Python对象拷贝——深拷贝与浅拷贝
对象赋值 浅拷贝 深拷贝 1. 对象赋值 对象的赋值实际上是对对象的引用.也就是说当把一个对象赋值给另一个对象时,只是拷贝了引用.如: >>> t1 = tuple('furzoom ...
- Python 深拷贝和浅拷贝的区别
python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 ...
- Python中的赋值、深拷贝与浅拷贝(内存地址)
Python中的赋值.深拷贝与浅拷贝(内存地址) 1.python中的可变对象与不可变对象 (1) 可变对象:dict,list def dict_test(): a = {} b = a print ...
- 对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解
引用:https://www.jb51.net/article/142775.htm 列表赋值: 1 2 3 4 5 6 7 >>> a = [1, 2, 3] >>&g ...
- python中的深拷贝和浅拷贝
python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一 ...
- Python的浅拷贝与深拷贝
定义: =号浅拷贝:在Python中对象的赋值其实就是对象的引用.copy了之后两个仍然是同一个东西.那么他们内部的元素自然也是一样的,对其中一个进行修改,另一个也会跟着变> copy()浅拷贝 ...
随机推荐
- OC实用转换model的工具
OC实用转换model的工具 说明 这是本人写的一个专门用来将json数据直接转换生成Model文件的工具,目的是为了让你从写Model文件的繁琐过程中解脱出来,提升效率以及减少出错的几率,工具的特点 ...
- Windows10自动更新之后,无线有线都连不上网
大概浪费了我至少6个小时. 一个是无线网卡,这个后来可以修复,其实也不是网卡的原因.最主要的原因是 Realtek PCIe GBE Family Controller 这个驱动.只找到一个win1 ...
- .Net WebApi 支持跨域访问使用 Microsoft.AspNet.WebApi.Cors
首先导入Cors库,通过程序包管理控制台导入 Install-Package Microsoft.AspNet.WebApi.Cors 引用库之后,我们需要进行简单的配置. 现在WebApiConfi ...
- 【原创】python __all__ 的用法
1. 写自己的module或者package的时候需要控制向外暴露的名字, 这个很有用, 防止名字污染
- ceph crush算法和crushmap浅析
1 什么是crushmap crushmap就相当于是ceph集群的一张数据分布地图,crush算法通过该地图可以知道数据应该如何分布:找到数据存放位置从而直接与对应的osd进行数据访问和写入:故障域 ...
- 【python库安装问题解决】UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 121: invalid start byte
好久没用python了...今天随便pip安装个库突然报错: Exception:‘’ (most recent call last): File "C:\ProgramData\Anac ...
- python第十七课——列表生成式
1.列表生成式: 什么是列表生成式? 它就是一串表达式,专门用于生成列表对象,当中包含一系列的业务逻辑: 结构:简介.优雅.阅读性好:比传统获取列表对象来的更加的方便: 它是语法糖的一种: 什么是语法 ...
- 来自苹果的编程语言——Swift简单介绍【整理】
2014年06月03日凌晨,Apple刚刚公布了Swift编程语言,本文从其公布的书籍<The Swift Programming Language>中摘录和提取而成.希望对各位的iOS& ...
- 微信小程序------导航栏样式、tabBar导航栏
一:导航栏样式设置 小程序的导航栏样式在app.json中定义. 这里设置导航,背景黑色,文字白色,文字内容测试小程序 app.json内容: { "pages":[ " ...
- ASP.NET Core读取appsettings.json配置文件信息
1.在配置文件appsettings.json里新增AppSettings节点 { "Logging": { "LogLevel": { "Defau ...