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,解释器会暂停,释放掉这个对象
和仅有这个对象可访问(可到达)的其它对象。作为引用计数的补充, 垃圾收集器也会留心被
分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下
来, 试图清理所有未引用的循环。
不太理解,先记录吧。
内存分配
作为一个负责任的程序员,我们知道在为变量分配内存时,是在借用系统资源,在用完之
后, 应该释放借用的系统资源。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,解释器会暂停,释放掉这个对象
和仅有这个对象可访问(可到达)的其它对象。作为引用计数的补充, 垃圾收集器也会留心被
分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下
来, 试图清理所有未引用的循环。
不太理解,先记录吧。
相关文章推荐
- Python动态类型的学习---引用的理解
- Python3写爬虫(四)多线程实现数据爬取
- 垃圾邮件过滤器 python简单实现
- 下载并遍历 names.txt 文件,输出长度最长的回文人名。
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- Python将excel导入到mysql中
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- FREEBASIC 编译可被python调用的dll函数示例
- Python 七步捉虫法