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]

[1] Python是如何进行内存管理的?

[2] Python的赋值、浅拷贝和深拷贝

[3] 从Python中copy与deepcopy的区别看Python引用

Python深拷贝和浅拷贝的更多相关文章

  1. python 深拷贝与浅拷贝

    浅拷贝的方式有: lst=[1,2,3] (1)直接赋值: lst_cp = lst (2)for循环遍历生成:lst_cp= [i for i in lst] (3)copy模块下,copy.cop ...

  2. 【python测试开发栈】—理解python深拷贝与浅拷贝的区别

    内存的浅拷贝和深拷贝是面试时经常被问到的问题,如果不能理解其本质原理,有可能会答非所问,给面试官留下不好的印象.另外,理解浅拷贝和深拷贝的原理,还可以帮助我们理解Python内存机制.这篇文章将会通过 ...

  3. Python深拷贝与浅拷贝区别

    可变类型 如list.dict等类型,改变容器内的值,容器地址不变. 不可变类型 如元组.字符串,原则上不可改变值.如果要改变对象的值,是将对象指向的地址改变了 浅拷贝 对于可变对象来说,开辟新的内存 ...

  4. Python 深拷贝和浅拷贝的区别

    python的复制,深拷贝和浅拷贝的区别    在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用  ...

  5. python深拷贝和浅拷贝的区别

    首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别. 什么是可变对象,什么是不可变对象: 可变对象 ...

  6. Python——深拷贝和浅拷贝

    深拷贝.浅拷贝 1. 浅拷贝 浅拷贝是对于一个对象的顶层拷贝 import copy a = [[1, 2], 3] b = copy.copy(a) print(id(a)) print(id(b) ...

  7. PYTHON 深拷贝,浅拷贝

    声明:本篇笔记,模仿与其它博客中的内容 浅拷贝 浅拷贝,在内存中只额外创建第一层数据 import copy n1 = {"k1": "wu", "k ...

  8. Python 深拷贝和浅拷贝

    Python中,对象的赋值,拷贝(深/浅拷贝)之间是有差异的,如果使用的时候不注意,就可能产生意外的结果. 下面本文就通过简单的例子介绍一下这些概念之间的差别. 对象赋值 直接看一段代码: will= ...

  9. Python深拷贝和浅拷贝!

    在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,[& ...

随机推荐

  1. 工作随笔记 点击除div自身之外的地方,关闭自己

    <div id="showSelectOptions" style="width:100px;height:100px;background-color:red;b ...

  2. Golang学习 - 学习资源列表

    Golang 学习资源: <Go 语言圣经(中文版)>  - 书籍 http://shinley.com/index.html <学习 Go 语言> - 书籍 http://w ...

  3. Sublime text 2下alignment插件无效的解决办法

    在sublime text 2中安装了alignment插件,但使用快捷键‘ctrl+alt+a'无效,经过各种方法依然无效,最后找到了这个“Doesn't work at all for me (f ...

  4. 如何编写自己的Linux安全检查脚本?

    因为本人工作中要涉及到很多东西,审计(日志.数据神马的).源代码审计.渗透测试.开发一大堆东西,有些东西,越是深入去做,越会发现,没有工具或脚本,工作起来是有多么的坑. 工作的这段时间,自己写了几个工 ...

  5. Design Mode 之 创建模式

    A.创建模式 首先,简单工厂模式不属于24种涉及模式. A0.简单工厂模式 简单工厂模式,分为三种:普通简单工厂.多方法简单工厂.静态方法简单工厂. A01.普通 就是建立一个工厂类,对实现了同一接口 ...

  6. 爬虫入门scrapy

    Python之路[第十九篇]:爬虫   网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...

  7. linux环境中 对tomcat配置java环境

    JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx2048m -XX:MaxPermSize=512m" JAVA_HOME="/weblogic1 ...

  8. [xPlugins] 开发中常用富文本编辑器介绍

    富文本编辑器学习,常见富文本编辑器有: CKeditor(FCkeditor).UEditor(百度推出的).NicEdit.KindEditor CKEditor 即 FCKEditor FCKed ...

  9. MySQL(23):事务的隔离级别出现问题之 脏读

    1. 脏读 所谓的脏读就是指一个事务读取了另一个事务未提取的数据. 试想一下:a账户要给b账户100元购买商品,如果a账户开启一个事务,执行下面的update语句做了如下转账的工作: update a ...

  10. [翻译] CBStoreHouseTransition

    CBStoreHouseTransition What is it? A custom transition inspired by Storehouse iOS app, also support ...