pythonソース剖析ノート1——Pythonオブジェクト初見


本文の簡単な住所:http://www.jianshu.com/p/763f6cec7a9b
仕事はちょうど2年になって、pythonを使うのが最も多くて、しかしpythonの内部のメカニズムに対してすべてはっきりしていないで、毎日添削して調べる簡単な論理の編纂に酔って、本当に気を消耗します.多くのものは忘れないで、例えばC言語、ちょうど、pythonソースコードはCで書いて、pythonソースコードを分析すると同時にC言語の基礎を温めることができて、本当に良いことです.また、陳儒大神の「pythonソース剖析」を導き、分析も頭がないほどではない.一ヶ月の余暇に、少しでも成功することを期待しています.
1 pythonのオブジェクト
pythonでは,すべてがオブジェクトであり,c言語実装では構造体に対応している.まずもちろんpythonの組み込みオブジェクトから見て、最も基本的なのはPyIntobject、PyStringObject、PyListObject、PyDictObjectのいくつかで、彼らはそれぞれint、string、list、dictタイプに属しています.python 2.2以降にnew style classがある場合、これらの組み込みオブジェクトはobjectタイプから継承され、objectはコードの中でPyBaseObject_に対応します.Type.例えば、文a=3を割り当てると、aはPyIntobjectオブジェクトであり、そのタイプはintであり、コードにはPyInt_に対応するType,PyInt_Typeもオブジェクトであり,我々はタイプオブジェクトと呼ぶ.ではPyInt_Typeそのタイプは何ですか.答えはtypeです.コードに対応するのがPyType_です.Type.もちろんobjectもタイプオブジェクトで、そのタイプもPyType_Type.このままいくとPyType_Typeもオブジェクトですが、そのタイプは何ですか.間違いなく、答えはそのタイプが自分です.次の検証コードを参照してください.
##      
In [1]: a = 3

In [2]: type(a)
Out[2]: int

In [3]: type(int)
Out[3]: type

In [4]: type(type)
Out[4]: type

In [5]: int.__base__
Out[5]: object

In [6]: type(object)
Out[6]: type

まずいくつかの基础の内建の対象のC言语の中の构造体とよく使ういくつかのマクロを分析して、便利のために、私も陈儒大神分析のそのバージョンが一致して、バージョンは2.5.6です.
//       
#define PyObject_HEAD \
        Py_ssize_t ob_refcnt;           \
        struct _typeobject *ob_type;

#define PyObject_HEAD_INIT(type) \
        1, type,

#define PyObject_VAR_HEAD \
        PyObject_HEAD                   \
        Py_ssize_t ob_size; /* Number of items in variable part */
#define Py_INVALID_SIZE (Py_ssize_t)-1

typedef struct _object {
        PyObject_HEAD
} PyObject;

typedef struct {
        PyObject_VAR_HEAD
} PyVarObject;

typedef struct _typeobject {
        PyObject_VAR_HEAD
        const char *tp_name; /* For printing, in format "<module>.<name>" */
        Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
        destructor tp_dealloc;
        printfunc tp_print;
        getattrfunc tp_getattr;
        setattrfunc tp_setattr;
        cmpfunc tp_compare;
        reprfunc tp_repr;
        ...
} PyTypeObject;

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;
    int ob_sstate;
    char ob_sval[1];
    /* Invariants: * ob_sval contains space for 'ob_size+1' elements. * ob_sval[ob_size] == 0. * ob_shash is the hash of the string or -1 if not computed yet. * ob_sstate != 0 iff the string object is in stringobject.c's * 'interned' dictionary; in this case the two references * from 'interned' to this object are *not counted* in ob_refcnt. */
} PyStringObject;

コードに示すように、PyObjectはすべてのPythonオブジェクトの基石であり、その後に見られるすべてのオブジェクトには同じPyObjectヘッダがあり、ソースコードにはすべてのオブジェクトがPyObject*ポインタで指し示すことができる.これがオブジェクト向けによく使われるマルチステートのテクニックである.Python内部の各関数オブジェクト間もPyObject*によって伝達され、それ自体がPyIntobjectタイプのオブジェクトであっても、コードにはPyIntobject*ポインタで伝達されないのも、マルチステートを実現するためである.たとえば、次の関数があります.
void Print(PyObject* object) {
    object->ob_type->tp_print(object);
}

また、コードに注記されているように、オブジェクトのob_が長くなるsizeとは、要素の数であり、バイト数ではありません.
2 pythonオブジェクト参照数
以下に、いくつかの一般的な操作オブジェクトがカウントを参照するマクロ定義(object.h)をいくつか挙げます.ここでは、デバッグ時に使用するコードを削除し、コードの意味がわかりやすいようにします.Py_NewReferenceは、初期化時のオブジェクトの場合に参照カウントを設定し、Py_INCREFとPy_DECREFは、それぞれ参照技術を増加させ、参照カウントを減少させるために使用される.コードからpythonが参照を増やしたり減らしたりするのは、これらのマクロによって動作していることがわかります.**オブジェクトがob_を参照している場合に注意してください.refcntが0に減少すると、オブジェクトの構造関数が呼び出されます.構造関数はfreeを呼び出してメモリ領域を解放するとは限りません.メモリの頻繁な申請と解放はパフォーマンスに深刻な影響を及ぼすため、pythonがメモリプール技術に多く使われていることを後で見ると、パフォーマンスの向上に大きな効果があります.
なお、タイプオブジェクトは参照カウントルールに含まれておらず、各オブジェクトがタイプオブジェクトを指すポインタはタイプオブジェクトの参照とはみなされません.つまり、タイプオブジェクトの参照カウントに影響を与えず、タイプオブジェクトは永遠に解析されません.
#define _Py_NewReference(op) ((op)->ob_refcnt = 1)


#define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op)))

#define Py_INCREF(op) ((op)->ob_refcnt++)

#define Py_DECREF(op) \
        if (--(op)->ob_refcnt != 0) \ ; else \ _Py_Dealloc((PyObject *)(op)) #define Py_CLEAR(op) \ do { \ if (op) { \ PyObject *tmp = (PyObject *)(op); \ (op) = NULL; \ Py_DECREF(tmp); \ } \ } while (0) /* Macros to use in case the object pointer may be NULL: */ #define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op) #define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op) 

3 Pythonオブジェクト分類
pythonのオブジェクトは、integer、float、boolean-シーケンスセットオブジェクトなどの数値オブジェクトに大きく分けられます.string、list、tuple-辞書オブジェクトなどです.dict-タイプオブジェクトなどです.type-内部オブジェクトなどです.後に表示されるcode、function、frame、module、methodオブジェクトなどです.
4参考資料
  • 『pythonソースプロファイル』