5

我试图弄清楚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
>>>

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

所以,在这里我试图弄清楚这个值存储在哪里或 python 如何获取它。

谢谢

4

3 回答 3

5

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

import gc, pprint
pprint.pprint(gc.get_referrers("string"))

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

typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

并且对象的引用计数分别使用宏Py_INCREF和递增和递减Py_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)
于 2014-02-14T09:41:26.387 回答
1

对象的引用计数存储在对象本身中,在表示该对象的 C 结构ob_refcnt的字段的 C 级字段中。ob_base您不能访问这些字段,或者至少不能通过obj.ob_base.ob_refcnt.

PyObject 的文档有点过时了。我相信PEP 3123对 PyObject 类型和 PyObject_HEAD 宏有更新的描述,但这也可能已经过时了。我会提供一个源链接,但我不知道这些东西是在源中定义的。

于 2014-02-14T09:49:13.993 回答
1

Python 对具有相同值的字符串文字使用相同的对象。也许,这就是为什么您可以在您的案例中看到出乎意料的高引用数。

例如,如果我尝试将 'string' 文字设置为多个字符串对象,您可以看到 's' 对象引用计数不断增加。

>>> s = 'string'
>>> sys.getrefcount(s)
2
>>> a = 'string'
>>> sys.getrefcount(s)
3
>>> b = 'string'
>>> sys.getrefcount(s)
4
于 2014-02-14T09:27:09.157 回答