Python 的垃圾回收机制(Garbage Collection, GC)是用来管理内存的自动化过程。它通过释放不再被使用的对象所占用的内存,确保程序的内存使用效率。Python 的垃圾回收主要基于 **引用计数** 和 **循环垃圾回收** 两种方式。以下是详细介绍:
---
## **1. 引用计数**
### 原理:
每个对象都有一个**引用计数器**,用于记录指向该对象的引用数量。当一个对象的引用计数变为 0 时,该对象的内存会被自动释放。
### 关键操作:
- **增加引用计数:**
- 当有新的引用指向对象时,计数加 1。
- 例如:`a = [1, 2, 3]` 后,列表 `[1, 2, 3]` 的引用计数为 1。
- **减少引用计数:**
- 当引用被删除或指向其它对象时,计数减 1。
- 例如:`a = None` 后,原来的列表引用计数减 1。
### 示例:
```python
import sys
a = [1, 2, 3]
print(sys.getrefcount(a)) # 输出:2(1个是变量a,1个是getrefcount函数的临时引用)
b = a
print(sys.getrefcount(a)) # 输出:3
del b
print(sys.getrefcount(a)) # 输出:2
```
### 优点:
- 简单高效,对绝大多数情况都适用。
### 局限性:
- **无法解决循环引用问题**。
```python
a = []
b = []
a.append(b)
b.append(a)
```
---
## **2. 循环垃圾回收**
Python 使用 `gc` 模块来处理**循环引用**。
### 工作原理:
- **分代回收机制**:
Python 将内存中的对象分为 3 代(Generation 0, 1, 2)。新创建的对象属于第 0 代,随着对象存活时间的增长,未被清理的对象会被移动到更高的代。
- **代的设计思想**:新对象大概率生命周期短,老对象大概率生命周期长。
- 垃圾回收更频繁地检查第 0 代,较少检查第 1 和第 2 代。
- **标记-清除**:
- **标记阶段**:标记所有存活的对象。
- **清除阶段**:删除未标记的对象。
### 触发条件:
- 当分配内存时触发。
- 当达到特定的阈值时触发。
- 手动触发:`gc.collect()`。
### 示例:
```python
import gc
gc.set_debug(gc.DEBUG_LEAK) # 启用调试模式
a = []
b = []
a.append(b)
b.append(a)
del a
del b
gc.collect() # 显式触发垃圾回收
```
---
## **3. GC 模块**
Python 提供了 `gc` 模块,允许用户管理和调试垃圾回收。
### 常用方法:
1. **查看启用状态**:
```python
import gc
print(gc.isenabled()) # 检查垃圾回收是否启用
```
2. **手动启动垃圾回收**:
```python
gc.collect() # 返回回收的对象数
```
3. **禁用垃圾回收**:
```python
gc.disable()
```
4. **设置阈值**:
```python
gc.set_threshold(700, 10, 10)
```
- 参数分别对应第 0、1、2 代的垃圾回收触发阈值。
---
## **4. 垃圾回收优化建议**
- **避免循环引用**:尽量避免在代码中创建循环引用。
- **显式删除对象**:通过 `del` 删除不再使用的变量。
- **使用弱引用**:对于不需要强引用的对象,可以使用 `weakref` 模块创建弱引用,避免增加引用计数。
```python
import weakref
class MyClass:
pass
obj = MyClass()
weak_obj = weakref.ref(obj)
print(weak_obj()) # 访问对象
del obj
print(weak_obj()) # 输出 None,弱引用不会阻止对象回收
```
---
通过以上机制,Python 实现了高效的内存管理,开发者可以在绝大多数情况下不用担心内存泄漏问题,但理解其工作原理有助于编写性能更优的代码。
806

被折叠的 条评论
为什么被折叠?



