[TOC]
一 引入
? 解释器在执行到定义变量的语法时, 会申请内存空间来存放变量的值, 而内存的容量是有限的, 这就涉及到变量值所占用内存空间的回收问题, 当一个变量值没有用了 (简称垃圾) 就应该将其占用的内存给回收掉, 那什么样的变量值是没有用的呢?
? 由于变量名是访问到变量值的唯一方式, 所以当一个变量值不再关联任何变量名时, 我们就无法再访问到该变量值了, 该变量值就是没有用的, 就应该被当成一个垃圾回收. 毫无疑问, 内存空间的申请与回收是非常耗费精力的事情, 而且存在很大的危险性, 稍有不慎就有可能引发内存溢出问题, 好在 Cpython 解释器提供了自动的垃圾回收机制来帮我们解决了这件事.
插图: 恶搞图 07
二, 什么是垃圾回收机制?
垃圾回收机制 (简称 GC) 是 Python 解释器自带一种机, 专门用来回收不可用的变量值所占用的内存空间
三, 为什么要用垃圾回收机制?
程序运行过程中会申请大量的内存空间, 而对于一些无用的内存空间如果不及时清理的话会导致内存使用殆尽(内存溢出), 导致程序崩溃, 因此管理内存是一件重要且繁杂的事情, 而 python 解释器自带的垃圾回收机制把程序员从繁杂的内存管理中解放出来.
插图: 恶搞图 08
四, 垃圾回收机制原理分析
Python 的 GC 模块主要运用了 "引用计数"(reference counting)来跟踪和回收垃圾. 在引用计数的基础上, 还可以通过 "标记 - 清除"(mark and sweep)解决容器对象可能产生的循环引用的问题, 并且通过 "分代回收"(generation collection)以空间换取时间的方式来进一步提高垃圾回收的效率.
插图:
4.1, 什么是引用计数?
引用计数就是: 变量值被变量名关联的次数
如: age=18
变量值 18 被关联了一个变量名 age, 称之为引用计数为 1
插图: 引用计数
引用计数增加:
- age=18 (此时, 变量值 18 的引用计数为 1)
- m=age (把 age 的内存地址给了 m, 此时, m,age 都关联了 18, 所以变量值 18 的引用计数为 2)
插图: 引用计数增加
引用计数减少:
- age=10(名字 age 先与值 18 解除关联, 再与 3 建立了关联, 变量值 18 的引用计数为 1)
- del m(del 的意思是解除变量名 x 与变量值 18 的关联关系, 此时, 变量 18 的引用计数为 0)
插图: 引用计数减少
值 18 的引用计数一旦变为 0, 其占用的内存地址就应该被解释器的垃圾回收机制回收
- # 如下我们定义了两个列表, 简称列表 1 与列表 2, 变量名 l1 指向列表 1, 变量名 l2 指向列表 2
- >>> l1=['xxx'] # 列表 1 被引用一次, 列表 1 的引用计数变为 1
- >>> l2=['yyy'] # 列表 2 被引用一次, 列表 2 的引用计数变为 1
- >>> l1.append(l2) # 把列表 2 追加到 l1 中作为第二个元素, 列表 2 的引用计数变为 2
- >>> l2.append(l1) # 把列表 1 追加到 l2 中作为第二个元素, 列表 1 的引用计数变为 2
- # l1 与 l2 之间有相互引用
- # l1 = ['xxx'的内存地址, 列表 2 的内存地址]
- # l2 = ['yyy'的内存地址, 列表 1 的内存地址]
- >>> l1
- ['xxx', ['yyy', [...]]]
- >>> l2
- ['yyy', ['xxx', [...]]]
- >>> l1[1][1][0]
- 'xxx'
- >>> del l1 # 列表 1 的引用计数减 1, 列表 1 的引用计数变为 1
- >>> del l2 # 列表 2 的引用计数减 1, 列表 2 的引用计数变为 1
来源: http://www.bubuko.com/infodetail-3347196.html