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

上記のスニペットでは、文字列オブジェクトを作成するとすぐにsref-count 28 を取得し、ディクショナリ内に割り当てると、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

ob_refcntオブジェクトの参照カウントは、オブジェクトを表す C 構造体のフィールドの 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 に答える