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 深拷贝,浅拷贝

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

  3. Python 深拷贝和浅拷贝

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

  4. python 深拷贝和浅拷贝浅析

    简单点说 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.id会变化2. copy.deepcopy 深拷贝 拷贝对象及其子对象.id会变化 >>> im ...

  5. python 中 深拷贝和浅拷贝的理解

    在总结 python 对象和引用的时候,想到其实 对于python的深拷贝和浅拷贝也可以很好对其的进行理解. 在python中,对象的赋值的其实就是对象的引用.也就是说,当创建一个对象,然后赋给另外一 ...

  6. 理解python可变类型vs不可变类型,深拷贝vs浅拷贝

    核心提示: 可变类型 Vs 不可变类型 可变类型(mutable):列表,字典 不可变类型(unmutable):数字,字符串,元组 这里的可变不可变,是指内存中的那块内容(value)是否可以被改变 ...

  7. python中的深拷贝与浅拷贝

    深拷贝和浅拷贝 浅拷贝的时候,修改原来的对象,浅拷贝的对象不会发生改变. 1.对象的赋值 对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷 ...

  8. Python 引用、浅拷贝、深拷贝解析

    引用 Python是动态数据类型的语言,故在对变量进行赋值时是不用制定变量类型的. 或者说,你可以把变量赋值的过程,当作是贴一个标签,去引用该数据. 看下面的例子: In [54]: a=4 In [ ...

  9. Python赋值语句与深拷贝、浅拷贝的区别

    参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...

随机推荐

  1. Java 清除数组相同元素

    定义一个函数清除该数组的重复元素,返回一个不能浪费长度的数组.代码如下: import java.util.*; public class demo1 { public static void mai ...

  2. 转《WF编程》笔记目录

    <WF编程>笔记目录 2008-03-18 09:33 by Windie Chai, 26803 阅读, 49 评论, 收藏, 编辑 WF笔记开始 <WF编程>系列之0 - ...

  3. js 获取小数点位数方法及 字符串与数字之间相互转换方法

    1.获取小数点位数方法 a. 使用 js 中 subsrting,indexOf,parseFloat三个函数,代码如下: var s = "22.127456" ;//s 为 字 ...

  4. poj1062昂贵的聘礼(Dijkstra**)

    /* 题意: 物主有一个物品,价值为P,地位为L, 以及一系列的替代品Ti和该替代品所对应的"优惠"Vi g[u][i] 表示的是u物品被i物品替换后的优惠价格!(u>0, ...

  5. 【GOF23设计模式】观察者模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_观察者模式.广播机制.消息订阅.网络游戏对战原理 package com.test.observer; import ja ...

  6. [HDOJ5439]Aggregated Counting(乱搞)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5439 题意:按规则构造一个数列a a(1)=1 a(2)=2 a(2)=2 -------> 写两个 ...

  7. Java面试常考知识点

    1.  什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. Jav ...

  8. Spring + Mybatis 使用 PageHelper 插件分页

    原文:http://www.cnblogs.com/yucongblog/p/5330886.html 先增加maven依赖: <dependency> <groupId>co ...

  9. 拉勾网ThoughtWorks面试题代码实现

    今天看到一个很有意思的面试活动(活动链接),不需要简历,只有一道编程题目,在线提交你的代码即可. 本菜鸟对面试不感兴趣,但题目让我很兴奋,特来挑战一下~ 或许当你看到这篇博文的时候活动已经失效了,所以 ...

  10. 用AE如何制作如下三个loading动效,

    在本期象牙绘UED团队分享当中,我们将详细演示用AE如何制作如下三个loading动效, 其中涉及到AE表达式的应用.值曲线调整.速度曲线编辑等知识. 对于初学者来说可能信息量略大,希望通过是视频教程 ...