美文网首页
Python引用计数的简单总结

Python引用计数的简单总结

作者: whosemario | 来源:发表于2017-02-23 13:43 被阅读0次

最近在用Python原生的API写一些逻辑,被维护PyObject引用计数搞得很是头疼,这里做些简单的总结,说明在什么时候一个PyObject会增加引用计数。

Python有几个存储操作:

  1. STORE_FAST
  2. STORE_GLOBAL
  3. STORE_NAME
  4. STORE_MAP
  5. ...

其实比较常见的也就是前两个,解析STORE_FAST说明一下Python是怎样操作引用计数的。

g_a = 1
def func(b):
    global g_a
    g_a = 1
    b = 2
    c = 3

上面func对应的字节码如下:

3           0 LOAD_CONST               1 (1)
            3 STORE_GLOBAL             0 (g_a)

4           6 LOAD_CONST               2 (2)
            9 STORE_FAST               0 (b)

5          12 LOAD_CONST               3 (3)
           15 STORE_FAST               1 (c)
           18 LOAD_CONST               0 (None)
           21 RETURN_VALUE

看一下STORE_FAST源码:

TARGET(STORE_FAST)
{
    v = POP();
    SETLOCAL(oparg, v);
    FAST_DISPATCH();
}

#define SETLOCAL(i, value)      do { PyObject *tmp = GETLOCAL(i); \
                                 GETLOCAL(i) = value; \
                                 Py_XDECREF(tmp); } while (0)
#define GETLOCAL(i)     (fastlocals[i])
                                 
#define BASIC_POP()       (*--stack_pointer)
#define POP()                  BASIC_POP()

可以看出来SETLOCAL只做减引用,不做加引用,我们可以认为stack_pointer里面的Object已经加过引用计数了,因此很容易去想到看一下LOAD_FAST的实现:

TARGET(LOAD_FAST)
{
    x = GETLOCAL(oparg);
    if (x != NULL) {
        Py_INCREF(x);   [1]
        PUSH(x);
        FAST_DISPATCH();
    }
    format_exc_check_arg(PyExc_UnboundLocalError,
        UNBOUNDLOCAL_ERROR_MSG,
        PyTuple_GetItem(co->co_varnames, oparg));
    break;
}

在[1]出会进行加引用,再PUSH到stack_pointer中。

好的,基本的逻辑也说搞明白了,总结如下:

任何的Object在PUSH到stack前,会有个地方进行加引用(这个地方可以是call_function内部,也可能就是字节码的内部实现,例如LOAD_CONST、LOAD_FAST等), POP处理的Object是不需要再加引用的!

那么什么时候对POP处理的Object解引用呢?这种情况就比较多了,比如如下代码:

TARGET(STORE_GLOBAL)
{
    w = GETITEM(names, oparg);
    v = POP();
    err = PyDict_SetItem(f->f_globals, w, v);
    Py_DECREF(v);   [1]
    if (err == 0) DISPATCH();
    break;
}

我们看到[1]处解引用了,因为SetItem的过程中会增加引用,因此v变量已经是个临时变量了,需要将v再减一次引用。

相关文章

  • Python引用计数的简单总结

    最近在用Python原生的API写一些逻辑,被维护PyObject引用计数搞得很是头疼,这里做些简单的总结,说明在...

  • 垃圾回收 gc

    python采用的是引用计数机制为主,隔代回收机制为辅的策略。 引用计数 引用计数机制的优点: 简单 实时性:一旦...

  • Python是如何进行内存管理的

    Python引入了一个机制:引用计数。 python内部使用引用计数,来保持追踪内存中的对象,Python内部记录...

  • python是如何进行内存管理的

    Python引入了一个机制:引用计数。 python内部使用引用计数,来保持追踪内存中的对象,Python内部记录...

  • python垃圾回收机制

    python的垃圾回收机制: 主要是引用计数为主,分代回收为辅。 一、引用计数 引用计数的原理: // objec...

  • python面试题之Python是如何进行内存管理的

    python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被...

  • python基础之内存管理

    一、对象的引用计数机制 1、定义:Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数 2、...

  • Day11-Python垃圾回收机制笔记

    Python中的垃圾回收是以引用计数为主,标记清除和分代回收为辅。 【引用计数】 Python默认的垃圾收集机制是...

  • python-垃圾回收机制

    前言 Python中,主要通过引用计数(Reference Counting)进行垃圾回收。 引用计数 在Pyth...

  • python爬虫面试题

    python是如何进行内存管理的? a、对象的引用计数机制 python内部使用引用计数,来保持追踪内存中的对象,...

网友评论

      本文标题:Python引用计数的简单总结

      本文链接:https://www.haomeiwen.com/subject/ijcbwttx.html