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,[& ...
随机推荐
- Device Pixel Ratio & Media Queries
一些重要的名词解释: CSS pixels(CSS 像素):详见http://www.w3.org/TR/css3-values/#reference-pixe CSS声明的像素值,可随着放大缩小而放 ...
- 实现一个不停发包的Android应用(类似于电脑上的Ping命令)
代码如下: package com.example.ping; import java.io.BufferedReader; import java.io.IOException; import ja ...
- 索引节点inode
在Linux的文件系统中,索引节点是文件的标识,并且这个值是唯一的,两个不同的文件的索引节点值是不同的,索引节点相同的文件它们的内容是相同的,仅仅文件名不同.修改两个索引节点值相同的文件中的一个文件, ...
- memmove和memcpy
1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向dest的void *指针 参 ...
- 16g u盘变 成1g u盘 解决方案,使用驱动器中的光盘之前需要将其格式化
1\ 计算机----管理------磁盘管理 有一个黑色区域是未分配的 2\ 1)进入cmd 命令行窗口2)输入 diskpart,并回车.弹出系统提示,选是即可.3)输入 list disk,并回 ...
- Android系统中设置TextView等的行间距
1.android:lineSpacingExtra 设置行间距,如”2dp”. 2.android:lineSpacingMultiplier 设置行间距的倍数,如”2″.
- Solr DIH dataconfig配置
1. 配置文件data-config.xml定义了数据库的基本配置,以及导出数据的映射规则,即导出数据库表中对应哪些字段的值,以及对特定字段的值做如何处理 </pre><p>& ...
- Unity3D 使用脚本来控制 UI 的 Image 显示的图片。
记录一下这个问题. 原文地址:http://tieba.baidu.com/p/3561719701 object obj = Resources.Load(资源名, typeof(Sprite)); ...
- centos下卸载rpm包
rpm -qa|grep sphinx rpm -e sphinx..... 安全地卸载 RPM卸载软件包,并不是简单地将原来安装的文件逐个删除,那样做的话,可能会出现这样或那样的问题.如,A软件包依 ...
- javaScript入门2--变量,作用域,内存
变量类型:基本类型和引用类型 基本类型上节已经提到.基本类型的值是按值传递的,既改变形参的值不会影响实参 <html> <head> <meta charset=&quo ...