سؤال

I was trying to figure out how python store the reference count of an object :

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
>>>

In my above snippet, as soon as i create a string object s i got the ref-count 28, then when i assigned inside a dictionary its ref-count increment by one. And I don't know why it starts with 28.

So, Here I am trying to figure out where this values store or how python get it.

Thanks

هل كانت مفيدة؟

المحلول

You can get the list of referrers to your object, using gc.get_referrers function, like this

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

The reference count of each and every object is stored in the object itself, in a variable called ob_refcnt

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

And the Reference counts of the objects are incremented and decremented using the macros Py_INCREF and Py_DECREF respectively.

#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)

نصائح أخرى

Python uses same object for string literal which have the same value. Maybe, that's why you can see unexpectedly high ref count in your case.

For example, if I try to set 'string' literal to multiple string object, as you can see 's' object reference count keep increasing.

>>> s = 'string'
>>> sys.getrefcount(s)
2
>>> a = 'string'
>>> sys.getrefcount(s)
3
>>> b = 'string'
>>> sys.getrefcount(s)
4

The reference count of an object is stored in the object itself, in the C-level ob_refcnt field of the ob_base field of the C struct representing the object. You can't access these fields, or at least not through anything like obj.ob_base.ob_refcnt.

The documentation for PyObject is a bit out of date. I believe PEP 3123 has a more recent description of the PyObject type and PyObject_HEAD macros, but that might be out of date too. I would provide a source link, but I have no idea where these things are defined in the source.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top