2022年 11月 7日

Python笔记,内存管理(1)—引用计数

引用计数
在python中,每个对象都有存有该对象的引用总数,即引用计数(feference count)

引用计数原理
1.每个对象维护一个ob_ref减1,用来记录该对象当前被引用的次数
2.每当新的引用指向该对象时,它的引用计数ob_ref加1
3.每当该对象的引用失效时ob_ref减1
4.一旦对象的引用计数为0,该对象可以被回收,对象占用的内存空间将被释放
5.它的缺点是需要额外的空间维护计数,这个问题是其次的
6.最主要的问题是它不能解决对象的“循环引用”

获取引用计数.getrefcount()

from sys import getrefcount
a = [1,2,3]
print(getrefcount(a))
b = a
print(getrefcount(b))

#结果:
        2
        3
# 当使用某个引用计数作为参数,传递给getrefcount()时,
#参数实际上创建了一个临时的引用,
#因此,getrefcount()所得到的的结果,会比期望多1.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

增加引用计数
当一个对象A被另一个对象B引用时,A的引用计数将加1

from sys import getrefcount
a = [1,2,3]
print(getrefcount(a))
b = [a,a]
print(getrefcount(a))

#结果:
        2
        4

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

减少引用计数
del删除或重新引用时,引用计数会变化(del只是删除引用)

from sys import getrefcount
a = [1,2,3]
b = a 
print(getrefcount(b))
del a
print(getrefcount(b))   

#结果:
       3
       2

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

循环引用的情况
x = []
y = []
x.append(y)
y,append(x)
对于上面相互引用的情况,如果不存在其他对象对他们的引用,
这两个对象所占用的内存也还是无法回收,从而到时内存泄露

        >>> x = []
		>>> y = []
		>>> x.append(y)
		>>> x = [1]
		>>> y = [2]
		>>> x.append(y)
		>>> x
		[1, [2]]
		>>> y.append(x)
		>>> y
		[2, [1, [...]]]
		>>> 
   

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14