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. UBUNTU 16.04 编译 OPENJDK8

    参考了几篇文章,和错误查询,最后总结如下 一.下载 我比较倾向于使用mercurial来获取源代码,虽然你得挑网络稳定的时候更新,但是易更新. 从官网查找一下,可以通过以下步骤完成源代码的下载 1. ...

  2. CSS3与页面布局学习笔记(四)——页面布局大全(负边距、双飞翼、多栏、弹性、流式、瀑布流、响应式布局)

    一.负边距与浮动布局 1.1.负边距 所谓的负边距就是margin取负值的情况,如margin:-100px,margin:-100%.当一个元素与另一个元素margin取负值时将拉近距离.常见的功能 ...

  3. javascript设计模式与开发实践

    1. js面向对象6种形式(详情) <!DOCTYPE html> <html> <head lang="en"> <meta chars ...

  4. kvc(键-值编码)

    kvc(键-值编码) { NSString *_name; Author *_author; NSArray *_kvcArray; float price;} //kvc,setValue 的设的值 ...

  5. oracle initialization or shutdown in progress解决方法

    [解决方法]   SQL> connect sys/hope as sysdba 已连接. SQL> shutdown normal ORA-01109: 数据库未打开     已经卸载数 ...

  6. 实现List按与一个字符串的相似度和字母顺序排序(适用于模糊查询后的排序)

    因公司业务需要,自己写了一个,保存起来以后可能还会用到.如果还有更好的方法或者算法,希望大家提出来. 1.简单的相似度算法(自己想到的)      因为List中每个String都会包含一个标准的字符 ...

  7. Android 利用SharedPreferences保存与删除 用户登录数据

    创建SharedPreferences对象: SharedPreferences sharedPreferences = context.getSharedPreferences("user ...

  8. 【linux】学习2

    鸟哥那本书的第6章 文件权限: ^                ^     ^      ^        ^              ^                 ^ 1         ...

  9. 小白学Linux(二)--命令行基本操作

    安装完Ubuntu后,进入系统,呈现在眼前的是Ubuntu的界面,跟windows的差不太多.一般操作系统包含GUI和CLI.GUI就是我们现在看到的,也是windows常用的直接用拖拽,点击等操作对 ...

  10. myeclipse ctrl+shift+F失效

    因为在使用搜狗输入法,切换到英文状态,输入ctrl+shift+F,格式化完之后,然后再换回来