来源:python中国网 时间:2019-06-06

  一.循环引用增减

  1、导致引用计数+1的情况

  对象被创建,例如a=23

  对象被引用,例如b=a

  对象被作为参数,传入到一个函数中,例如func(a)

  对象作为一个元素,存储在容器中,例如list1=[a,a]

  2、导致引用计数-1的情况

  对象的别名被显式销毁,例如dela

  对象的别名被赋予新的对象,例如a=24

  一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)

  对象所在的容器被销毁,或从容器中删除对象

  3、查看一个对象的引用计数

  import sys

  a="helloworld"

  sys.getrefcount(a)

  可以查看a对象的引用计数,但是比正常计数大1,因为调用函数的时候传入a,这会让a的引用计数+1

  二.循环引用导致内存泄露

  引用计数的缺陷是循环引用的问题

# -*- coding: utf-8 -*-
import gc

class ClassA():
    def __init__(self):
        print('object born,id:%s'%str(hex(id(self))))

def f2():
    while True:
        c1 = ClassA()
        c2 = ClassA()
        c1.t = c2
        c2.t = c1
        del c1
        del c2

#把python的gc关闭
gc.disable()

f2()

  执行f2(),进程占用的内存会不断增大。

  创建了c1,c2后这两块内存的引用计数都是1,执行c1.t=c2和c2.t=c1后,这两块内存的引用计数变成2.

  在del c1后,内存1的对象的引用计数变为1,由于不是为0,所以内存1的对象不会被销毁,所以内存2的对象的引用数依然是2,在del c2后,同理,内存1的对象,内存2的对象的引用数都是1。

  虽然它们两个的对象都是可以被销毁的,但是由于循环引用,导致垃圾回收器都不会回收它们,所以就会导致内存泄露。