@songying
2018-07-28T13:48:17.000000Z
字数 991
阅读 1112
python高级特性
参考: https://foofish.net/python-gc.html
对象绝不会自行销毁;然而,无法得到对象时,可能会被当作垃圾回收
GC作为现代编程语言的自动内存管理机制,专注于两件事:
1. 找到内存中无用的垃圾资源
2. 清除这些垃圾并把内存让出来给其他对象使用。
del语句删除名称,而不是对象。del命令可能会导致对象被当作垃圾回收,但是仅当删除的变量保存的是对象的最后一个引用,或者无法得到对象时。
原理: 每个对象维护一个
ob_ref
字段,用来记录该对象当前被引用的次数,每当新的引用指向该对象时,它的引用计数ob_ref
加1,每当该对象的引用失效时计数ob_ref
减1,一旦对象的引用计数为0,该对象立即被回收,对象占用的内存空间将被释放。
在cpython中, 会在对象上调用 __del__
方法(如果定义了),然后释放分配给对象的内存。
缺点:
- 需要额外的空间维护引用计数
- 不能解决对象的“循环引用”。
导致引用计数+1的情况:
- 对象被创建,例如a=23
- 对象被引用,例如b=a
- 对象被作为参数,传入到一个函数中,例如func(a)
- 对象作为一个元素,存储在容器中,例如list1=[a,a]
- 对象的别名被显式销毁,例如del a
- 对象的别名被赋予新的对象,例如a=24
- 一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
- 对象所在的容器被销毁,或从容器中删除对象
A和B相互引用而再没有外部引用A与B中的任何一个,它们的引用计数虽然都为1,但显然应该被回收
a = { } #对象A的引用计数为 1
b = { } #对象B的引用计数为 1
a['b'] = b #B的引用计数增1
b['a'] = a #A的引用计数增1
del a #A的引用减 1,最后A对象的引用为 1
del b #B的引用减 1, 最后B对象的引用为 1
对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。
Cpython中使用的是该算法。