python对象如何存储垃圾收集的引用计数器

5 python garbage-collection python-internals

我试图找出python如何存储对象的引用计数:

getrefcount(...)
    getrefcount(object) -> integer

    Return the reference count of object.  The count returned is generally
    one higher than you might expect, because it includes the (temporary)
    reference as an argument to getrefcount().
    >>>

>>> s = 'string'
>>> sys.getrefcount(s)
28
>>> d = {'key' : s}
>>> sys.getrefcount(s)
29
>>> l = [s]
>>> sys.getrefcount(s)
30
>>> del l
>>> sys.getrefcount(s)
29
>>> del d
>>> sys.getrefcount(s)
28
>>>
Run Code Online (Sandbox Code Playgroud)

在我上面的代码片段中,一旦我创建了一个字符串对象,s我得到了ref-count 28,然后当我在字典中分配它的ref-count增加1.我不知道为什么它从28开始.

所以,在这里我试图找出这个值存储的位置或python如何获取它.

谢谢

the*_*eye 5

您可以使用gc.get_referrers函数获取对象的引用列表,如下所示

import gc, pprint
pprint.pprint(gc.get_referrers("string"))
Run Code Online (Sandbox Code Playgroud)

每个对象的引用计数存储在对象本身中,在一个名为的变量中 ob_refcnt

typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;
Run Code Online (Sandbox Code Playgroud)

和对象的引用计数递增,并使用宏递减Py_INCREFPy_DECREF分别.

#define Py_INCREF(op) (                         \
    _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
    ((PyObject*)(op))->ob_refcnt++)

#define Py_DECREF(op)                                   \
    do {                                                \
        if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
        --((PyObject*)(op))->ob_refcnt != 0)            \
            _Py_CHECK_REFCNT(op)                        \
        else                                            \
        _Py_Dealloc((PyObject *)(op));                  \
    } while (0)
Run Code Online (Sandbox Code Playgroud)