您的位置:首页 > 编程语言 > Python开发

Python 核心编程笔记_Chapter_3 Note_3 内存管理_垃圾回收

2016-06-29 11:33 771 查看
想了想还是单独做一份关于内存管理的笔记,因为这个基础知识比较重要,而且自己没什么概念。

内存分配

作为一个负责任的程序员,我们知道在为变量分配内存时,是在借用系统资源,在用完之

后, 应该释放借用的系统资源。Python 解释器承担了内存管理的复杂任务, 这大大简化了应

用程序的编写。你只需要关心你要解决的问题,至于底层的事情放心交给Python 解释器去做就

行了。

3.5.4 引用计数

要保持追踪内存中的对象, Python 使用了引用计数这一简单技术。也就是说Python 内部

记录着所有使用中的对象各有多少引用。你可以将它想像成扑克牌游戏“黑杰克”或“21 点”。

一个内部跟踪变量,称为一个引用计数器。至于每个对象各有多少个引用, 简称引用计数。当

对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的

引用计数变为0 时, 它被垃圾回收。(严格来说这不是100%正确,不过现阶段你可以就这么

认为)

以上这段是摘抄自书籍,然后下面的我们来看看书籍上的案例说明

增加引用计数

当对象被创建并(将其引用)赋值给变量时,该对象的引用计数就被设置为1。

当同一个对象(的引用)又被赋值给其它变量时,或作为参数传递给函数, 方法或类实例

时, 或者被赋值为一个窗口对象的成员时,该对象的一个新的引用,或者称作别名,就被创建

(则该对象的引用计数自动加1)。



x = 3.14

y = x
语句 x=3.14 创建了一个浮点数对象并将其引用赋值给 x。 x 是第一个引用, 因此,该

对象的引用计数被设置为1。语句 y=x 创建了一个指向同一对象的别名 y(参阅图3-2)。事

实上并没有为Y 创建一个新对象, 而是该对象的引用计数增加了1 次(变成了2)。这是对象
引用计数增加的方式之一。还有一些其它的方式也能增加对象的引用计数, 比如该对象作为参

数被函数调用或这个对象被加入到某个容器对象当中时。

总之,对象的引用计数在

对象被创建

x = 3.14              3.14是对象,被复制给x,所以3.14这个对象的计数加1
或另外的别名被创建

y = x                   通过y这个别名,被引用赋值,所以对象计数再加1
或被作为参数传递给函数(新的本地引用)

foobar(x)             作为函数内的变量参数被引用,对象计数加1
或成为容器对象的一个元素      作为容器对象内的一个元素,对象计数加1
myList = [123, x, 'xyz']

我自己的理解,就是一个对象,被引用了,就要计数加1,至于这个计数累加了以后再内存中如何运作和作用,没什么概念,以后再补。

减少引用计数

当对象的引用被销毁时,引用计数会减小。最明显的例子就是当引用离开其作用范围时,

这种情况最经常出现在函数运行结束时,所有局部变量都被自动销毁,对象的引用计数也就随

之减少。

当变量被赋值给另外一个对象时,原对象的引用计数也会自动减1:

foo = 'xyz'       'xyz'对象被引用赋值,计数加1
bar = foo         被bar别名引用,计数加1
foo = 123        引用赋值的对象被赋予其他值了,计数减1
当字符串对象"xyz"被创建并赋值给foo 时, 它的引用计数是1. 当增加了一个别名 bar

时, 引用计数变成了2. 不过当foo 被重新赋值给整数对象123 时, xyz 对象的引用计数自

动减1,又重新变成了1.

其它造成对象的引用计数减少的方式包括使用 del 语句删除一个变量(参阅下一节), 或

者当一个对象被移出一个窗口对象时(或该容器对象本身的引用计数变成了0 时)。 总结一下,

一个对象的引用计数在以下情况会减少:

一个本地引用离开了其作用范围。比如 foobar()(参见上一下例子)函数结束时。
对象的别名被显式的销毁。

del y # or del x

对象的一个别名被赋值给其它的对象

x = 123

对象被从一个窗口对象中移除

myList.remove(x)

窗口对象本身被销毁

del myList # or goes out-of-scope

del 语句

Del 语句会删除对象的一个引用,它的语法是:

del obj1[, obj2[,... objN]]

例如,在上例中执行del y 会产生两个结果:

从现在的名字空间中删除 y
x 的引用计数减一

引申一步, 执行 del x 会删除该对象的最后一个引用, 也就是该对象的引用计数会减为
0, 这会导致该对象从此“无法访问”或“无法抵达”。 从此刻起, 该对象就成为垃圾回收

机制的回收对象。 注意任何追踪或调试程序会给一个对象增加一个额外的引用, 这会推迟该
对象被回收的时间。


垃圾收集

不再被使用的内存会被一种称为垃圾收集的机制释放。象上面说的, 虽然解释器跟踪对象

的引用计数, 但垃圾收集器负责释放内存。垃圾收集器是一块独立代码, 它用来寻找引用计

数为0 的对象。它也负责检查那些虽然引用计数大于0 但也应该被销毁的对象。 特定情形会导

致循环引用。

一个循环引用发生在当你有至少两个对象互相引用时, 也就是说所有的引用都消失时, 这

些引用仍然存在, 这说明只靠引用计数是不够的。Python 的垃圾收集器实际上是一个引用计

数器和一个循环垃圾收集器。 当一个对象的引用计数变为0,解释器会暂停,释放掉这个对象

和仅有这个对象可访问(可到达)的其它对象。作为引用计数的补充, 垃圾收集器也会留心被

分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下

来, 试图清理所有未引用的循环。

不太理解,先记录吧。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息