聊一聊 Python 对象的「垃圾收集」那些事儿。
00.写在之前
有时候写代码玩,懒得去想变量名的时候,你可能会做出下面这样的举动:
>>> a = 1
>>> a = 2.0
>>> a = 'Rocky'
虽然可能看着有些奇怪,a 刚开始是个整数,然后又变成了浮点数,最后变成了一个字符串,但它确实是可行的,这个也符合我在上篇文章 浅谈动态类型领域中 Python 的变量、对象以及引用。 中所说的「变量本身就是通用的,它只是恰巧在某个时间点上引用了当时的特定对象而已」。
同样我在上一篇文章中也说过在 Python 内部是「变量引用对象」,我不知道大家在看到上面的代码时脑袋里有没有产生过这么一个疑问:当我重新给变量 a 赋值的时候,它的前一个引用值去哪了?也就是当我给 a 重新赋值为 2.0 的时候,1 这个值去哪了?
答案是每当一个变量被重新赋予一个新的对象,如果之前的对象没有被其他变量名或者对象引用的话,那么之前的对象所占用的空间就会被回收。这种自动回收对象空间的做法就叫对象的「垃圾收集」。
01.垃圾收集
为了更好的搞明白,我们还是用上面说过的那个例子:
>>> a = 1
>>> a = 2.0
>>> a = 'Rocky'
上面的例子中,a 每次都是被设置成了不同类型的对象,尽管我们心知这不是真正的情况,但达成的效果却是变量的类型每次都在改变,这种代码行得通的原因还是我无数次强调过的:「类型属于的是对象,不是变量,变量只是引用了对象而已」。
在重新赋值的过程中,变量是引用了新的对象,旧的对象在此过程中一个一个的被丢弃,Python 回收了它们的空间。比如说,当 a 赋值为 2.0 的时候,对象 1 如果没有被其他对象引用的话,它就会马上被回收,空出来的空间自动放入自由内存空间池,等待着后来者使用。
可能到这你会有这个问题,Python 怎么知道一个对象又没有被其它对象引用呢?这个就需要我们来探究 Python 内部是怎样来实现这个功能的,其实也没什么大不了的,就是是靠一个叫「计数器」的东西。
Python 在每个对象中放了一个计数器,计数器记录的是当前指向这个对象的引用数目,一旦这个计数器成了零,这个对象的所在的内存空间就会被自动回收。在上述例子中,a 每次都被赋值给一个新的对象,而旧对象的计数器成了零,从而旧对象的空间被回收掉。
02.写在之后
从「垃圾回收」其实也可以看出动态语言对比静态语言的“省心”,Python 程序运行的时候会清理掉不用的内存空间,这就意味着我们可以在写的代码中“任性”的使用对象(当然这个做法不推荐)而不需要去考虑释放内存空间这种“烦心事”,这样相比 C 或者 C++ 来说,可以偷懒少写不少东西。
- 由索引节点(inode)爆满引发的问题
- As3.0中的位图(Bitmap/BitmapData)编程
- Mesos+Zookeeper+Marathon的Docker管理平台部署记录(2)--负载均衡marathon-lb
- Docker集群管理工具-Kubernetes部署记录
- AS3:小游戏“贪吃蛇”的实现
- 超实用的8个Linux命令行性能监测工具
- 用javascript替换URL中的参数值
- Gitblit版本服务器环境部署记录
- HDK扩展自定义VEX函数print
- AsyncTask和Handler对比
- sql初始化XML操作
- 给你一根杠杆,撬起万亿的小程序红利市场!
- Flash/Flex学习笔记(43):动量守恒与能量守恒
- Flash/Flex学习笔记(57):实用技巧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 带命令行控制台的轻量级日志分析工具-GoAccess
- 七日Python之路--第八天
- Go 语言学习之运算符
- 神奇!如何快速成为一名优秀的YAML工程师?
- 移动端H5开发入门
- Go 语言学习之流程控制
- MinGW 安装
- 实践 | 目前最快精度最高检测框架(EfficientDet)
- 解决拉取github仓库报错“gnutls_handshake() failed”问题
- HTML 学习
- Go 语言学习之数组
- 坐姿不对,屏幕就变模糊!小姐姐教你用TensorFlow做一款“隐形背背佳”
- 七日Python之路--第九天(blog与Django)
- Python数据可视化-seaborn Iris鸢尾花数据
- pythonGUI -- pyside安装与初试