Python深拷贝和浅拷贝
1- Python引用计数[1]
1.1 引用计数机制
引用计数是计算机编程语言中的一种内存管理技术,是指将资源(可以是对象、内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的过程。使用引用计数技术可以实现自动资源管理的目的。同时引用计数还可以指使用引用计数技术回收未使用资源的垃圾回收算法。
当创建一个对象的实例并在堆上申请内存时,对象的引用计数就为1,在其他对象中需要持有这个对象时,就需要把该对象的引用计数加1,需要释放一个对象时,就将该对象的引用计数减1,直至对象的引用计数为0,对象的内存会被立刻释放。
1.2 垃圾回收
当对象的引用计数为0,对象的内存会被立刻释放,称为垃圾回收。
1.3 引用计数增加情况
(1). 对象被创建:x=4
(2). 另外的别人被创建:y=x
(3). 被作为参数传递给函数:foo(x)
(4). 作为容器对象的一个元素:a=[1,x,'33']
1.4 引用计数减少情况
(1). 一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。
(2). 对象的别名被显式的销毁:del x ;或者del y
(3). 对象的一个别名被赋值给其他对象:x=789
(4). 对象从一个窗口对象中移除:myList.remove(x)
(5). 窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。
2- 深浅拷贝[2,3]
2.1 赋值
其实python中的赋值其实是使引用计数+1,例如:
foo1 = 1.0
foo2 = foo1
foo1 is foo2 #True
id(foo1) = 18719720
id(foo2) = 18719720
但是如果是这样:
foo1=1.0
foo2=1.0
foo1 is foo2 #False
id(foo1) = 18719888
id(foo2) = 18719840
这时你会发现,这其实是创建了两个不同的对象,用内建函数id()可以发现,二者的身份不同。
其实python还有一个特例,例如:
a = 1
b = 1
id(a) = 14332248
id(b) = 14332248
原因是python认为这些小整型是会经常用到的,所以python会缓存一部分小整型。
2.2 深拷贝 & 浅拷贝
序列类型的可以通过三种方式实现浅拷贝,浅拷贝也是默认的拷贝类型:(1)完全切片操作;(2)利用工厂函数,比如list()等;(3)使用copy模块中的copy()函数。
在《Python核心编程》一书中说道,“对一个对象进行浅拷贝其实是新创建了一个类型跟原对象一样,其内容是原来对象元素的引用,换句话说,这个拷贝的对象本身是新的,但是它的内容不是”。
import copy
a = [1, 2, 3, 4, ['a', 'b', 'c']]
b = a
c = copy.copy(a) id(a) #139879301469392
id(b) #139879301469392
id(c) #139879298646816, 可以看出所谓的“拷贝对象本身是新的“ [id(x) for x in a] #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in b] #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in c] #[14332248, 14332224, 14332200, 14332176, 139879298781912], 即”内容是旧的“
最后,深拷贝和浅拷贝的区别^_^
import copy
a = [1, 2, 3, 4, ['a', 'b', 'c']]
c = copy.copy(a)
d = copy.deepcopy(a) id(a) #139879301469392
id(c) #
id(d) # [id(x) for x in a] #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in c] #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in d] #[14332248, 14332224, 14332200, 14332176, 139879302072512] ##################################
a.append(5)
a[4].append('hello') a #[1, 2, 3, 4, ['a', 'b', 'c', 'hello'], 5]
c #[1, 2, 3, 4, ['a', 'b', 'c', 'hello']]
d #[1, 2, 3, 4, ['a', 'b', 'c']] [id(x) for x in a] #[14332248, 14332224, 14332200, 14332176, 139879298781912, 14332152]
[id(x) for x in c] #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in d] #[14332248, 14332224, 14332200, 14332176, 139879302072512] #################################
a[1] = 0
c[2] = 0
d[3] = 0 a #[1, 0, 3, 4, ['a', 'b', 'c', 'hello'], 5]
c #[1, 2, 0, 4, ['a', 'b', 'c', 'hello']]
d #[1, 2, 3, 0, ['a', 'b', 'c']] [id(x) for x in a] #[14332248, 14332272, 14332200, 14332176, 139879298781912, 14332152] a[1]关联到新对象 [id(x) for x in c] #[14332248, 14332224, 14332272, 14332176, 139879298781912] c[2]关联到新对象 [id(x) for x in d] #[14332248, 14332224, 14332200, 14332272, 139879302072512] d[3]关联到新对象
################################
#
del a[0]
a #[ 0, 3, 4, ['a', 'b', 'c', 'hello'], 5]
c #[1, 2, 0, 4, ['a', 'b', 'c', 'hello']]
d #[1, 2, 3, 0, ['a', 'b', 'c']] del c[0]
a #[ 0, 3, 4, ['a', 'b', 'c', 'hello'], 5]
c #[ 2, 0, 4, ['a', 'b', 'c', 'hello']]
d #[1, 2, 3, 0, ['a', 'b', 'c']] del d[0]
a #[ 0, 3, 4, ['a', 'b', 'c', 'hello'], 5]
c #[ 2, 0, 4, ['a', 'b', 'c', 'hello']]
d #[ 2, 3, 0, ['a', 'b', 'c']] #
del a[3][0]
a #[ 0, 3, 4, [ 'b', 'c', 'hello'], 5]
c #[ 2, 0, 4, [ 'b', 'c', 'hello']]
d #[ 2, 3, 0, ['a', 'b', 'c']]
简单点说
1. copy.copy 浅拷贝 -拷贝一个对象,但是对象的属性还是引用原来的。拷贝了一个不可变的对象的引用, 修改你得到的变量只会让该变量的引用指向一个新的对象(如a或c中数值元素改变不会影响另一个)
可以这样记忆,浅拷贝的各个元素整体上改变是没有影响的,但仅元素部分修改是互相牵制的
a = [1, 2, ['a', 'b'], ['c', 'd']]
b = copy.copy(a) #整体
a[0] = 0
a #[0, 2, ['a', 'b'], ['c', 'd']]
b #[1, 2, ['a', 'b'], ['c', 'd']] del a[3]
a #[0, 2, ['a', 'b']]
a #[1, 2, ['a', 'b'], ['c', 'd']] #局部
a[2].append('haha')
a #[0, 2, ['a', 'b', 'haha']]
a #[1, 2, ['a', 'b', 'haha'], ['c', 'd']]
2. copy.deepcopy 深拷贝 -拷贝一个对象,把对象里面的属性也做了拷贝,deepcopy之后完全是另一个对象了,实现完全独立
#打印['a','b','c']地址
[id(x) for x in a[3]] #[1398793470232, 139879343471752, 139879314380720]
[id(x) for x in c[3]] #[1398793470232, 139879343471752, 139879314380720]
[id(x) for x in d[3]] #[1398793470192, 139879343470232, 139879343471752]
[3] 从Python中copy与deepcopy的区别看Python引用
Python深拷贝和浅拷贝的更多相关文章
- python 深拷贝与浅拷贝
浅拷贝的方式有: lst=[1,2,3] (1)直接赋值: lst_cp = lst (2)for循环遍历生成:lst_cp= [i for i in lst] (3)copy模块下,copy.cop ...
- 【python测试开发栈】—理解python深拷贝与浅拷贝的区别
内存的浅拷贝和深拷贝是面试时经常被问到的问题,如果不能理解其本质原理,有可能会答非所问,给面试官留下不好的印象.另外,理解浅拷贝和深拷贝的原理,还可以帮助我们理解Python内存机制.这篇文章将会通过 ...
- Python深拷贝与浅拷贝区别
可变类型 如list.dict等类型,改变容器内的值,容器地址不变. 不可变类型 如元组.字符串,原则上不可改变值.如果要改变对象的值,是将对象指向的地址改变了 浅拷贝 对于可变对象来说,开辟新的内存 ...
- Python 深拷贝和浅拷贝的区别
python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 ...
- python深拷贝和浅拷贝的区别
首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别. 什么是可变对象,什么是不可变对象: 可变对象 ...
- Python——深拷贝和浅拷贝
深拷贝.浅拷贝 1. 浅拷贝 浅拷贝是对于一个对象的顶层拷贝 import copy a = [[1, 2], 3] b = copy.copy(a) print(id(a)) print(id(b) ...
- PYTHON 深拷贝,浅拷贝
声明:本篇笔记,模仿与其它博客中的内容 浅拷贝 浅拷贝,在内存中只额外创建第一层数据 import copy n1 = {"k1": "wu", "k ...
- Python 深拷贝和浅拷贝
Python中,对象的赋值,拷贝(深/浅拷贝)之间是有差异的,如果使用的时候不注意,就可能产生意外的结果. 下面本文就通过简单的例子介绍一下这些概念之间的差别. 对象赋值 直接看一段代码: will= ...
- Python深拷贝和浅拷贝!
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,[& ...
随机推荐
- LeetCode44 Wildcard Matching
题目: Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single charact ...
- IIS 之 打开/关闭 Internet 信息服务
由于建立测试网站测试代码,重装电脑后不知道IIS在哪打开.下面以windows7为例介绍,打开IIS管理器的简要步骤. 第一步.查找IIS 1.点击" 开始 "→" 控制 ...
- 美国H1B基本情况及相关数据
H-1B是外国人在美国工作的签证,从美国学校毕业之后会有12个月的OPT实习期,在OPT结束之前必须申请到H1B签证才能在实习期结束后继续工作. H1B需要由雇佣你的公司帮你申请,也就是说必须先找到工 ...
- Emacs golang 配置
在配置前需要下载用到的包: godoc godef gocode oracle 在下载包之前需要设置好环境变量: # Golang export GOROOT=$HOME/go export GOPA ...
- iOS webview加载html自定义选项框选词
项目要求:webview加载html网址,内容为英文文本,需要获取文本上的单词 这个是最终效果图: 思路是先实现自定义的选项框(不带系统选项)再获取到滑选的单词: 实现的步骤: 首先是替换掉系统长按出 ...
- iOS 真机测试的一些报错
1.连了手机热点 fix Issue后出现提示框:No Devices Registered:Creating a provisioning profile requires one or more ...
- iOS之GCD的局部解析
一什么是GCD :(Grand [伟大] Central [中央] Dispatch[调度]) GCD又名“伟大的中央调度器”,他是iOS4后才引进的一种多线程技术.开发者只需定义想执行的任务兵追加 ...
- SQL Server中游标的使用
举个栗子: -- 临时变量 DECLARE @Id UNIQUEIDENTIFIER -- 声明游标名 DECLARE cursor_name CURSOR FOR SELECT ID from CO ...
- OS X 10.10 apache配置
配置内容转自:http://www.linuxidc.com/Linux/2015-04/116347.htm 一.apache的配置 apache已经自带了,只需如下三个命令就可以了. 开启apac ...
- git and github学习笔记
1.git的状态分为working status,stage status和commit status.git diff查看的是working status和 stage status之间的不同,gi ...