Python2.7内存回收机制(一)
写在前面
Python
的内存回收采用引用计数机制。引用计数是一种简单而广泛使用的资源回收机制,例如Linux
平台的文件描述符,Windows
平台下的内核对象等均采用引用计数的方式进行管理。本文将结合Python2.7
官方手册阐明Python2.7
的引用计数机制(如无特殊说明,本文所提及的Python
均为CPython
)。
Python
语言在设计之初就是一门面向对象的语言,即一切皆为对象,在Python
官方介绍通用对象结构Common Object Structures
一文中,有这样一段话:
All Python objects ultimately share a small number of fields at the beginning of the object’s representation in memory. These are represented by the
PyObject
andPyVarObject
types, which are defined, in turn, by the expansions of some macros also used, whether directly or indirectly, in the definition of all other Python objects.
简单来说,Python
中所有对象的开始位置,都有一组成员变量,以C
语言的两个自定义类型——PyObject
与PyVarObject
来表示(有兴趣的,可以通读Common Object Structures
一文,或者参考《Python源代码剖析
》一书,这里不做具体阐述),PyObject
与PyVarObject
的开始位置都有一组相同的成员变量(分别由宏PyObject_HEAD
,PyObject_HEAD
扩展):
1 | Py_ssize_t ob_refcnt; // 对象引用计数 |
由此可见,在CPython
实现中,每个Python
对象均有一个名为ob_refcnt
的成员变量用于标识该对象的引用计数。而众所周知,在Python
的实现中,变量只是保存了一个对象的引用(即指针),而非对象本身,所以每当一个Python
对象被一个不同变量所引用时,对象的引用计数就会+1,相反当变量不再引用该对象时,该对象的引用计数就会-1,当对象的引用计数变为0时,该对象就会在未来的某个时间被Python
的垃圾回收器所回收。
通过Python
的sys
模块的getrefcount
方法可以获取Python
对象的当前引用计数:
1 | # -*- coding: utf-8 -*- |
示例运行结果为4,比实际引用数量(a, b, c)多1,那么为什么会这样呢,`sys.getrefcount`的文档作出了说明:
>Return the reference count of the *object*. The count returned is generally one higher than you might expect, because it includes the (temporary) reference as an argument to [`getrefcount()`](https://docs.python.org/2.7/library/sys.html#sys.getrefcount).
把对象当做参数调用`sys.getrefcount`方法会增加对象的一个临时引用计数。