10.2 共通のオブジェクト構造体 (common object structure)

Python では、オブジェクト型を定義する上で数多くの構造体が使われます。 この節では三つの構造体とその利用方法について説明します。

全ての Python オブジェクトは、オブジェクトのメモリ内表現の先頭部分に ある少数のフィールドを完全に共有しています。このフィールドは PyObject および PyVarObject 型で表現されます。 PyObject 型や PyVarObject 型もまた、他の全ての Python オブジェクトを定義する上で直接的・間接的に使われているマクロを 使って定義されています。

PyObject
全てのオブジェクト型はこの型を拡張したものです。 この型には、あるオブジェクトに対するオブジェクトとしてのポインタを Python から扱う必要がある際に必要な情報が入っています。 通常に ``リリースされている'' ビルドでは、この構造体にはオブジェクトの 参照カウントと、オブジェクトに対応する型オブジェクトだけが入っています。

PyObject_HEAD マクロ展開で定義されているフィールドに対応します。

PyVarObject
PyObject を拡張して、ob_size フィールドを追加した ものです。この構造体は、長さ (length) の概念を持つオブジェクト だけに対して使います。この型が Python/C API で使われることは ほとんどありません。 PyObject_VAR_HEAD マクロ展開で定義されているフィールドに対応します。

PyObject および PyVarObject の定義には以下のマクロが 使われています:

PyObject_HEAD
PyObject 型のフィールド宣言に展開されるマクロです; 可変でない長さを持つオブジェクトを表現する新たな型を宣言する 場合に使います。展開によってどのフィールドが宣言されるかは、 Py_TRACE_REFS の定義に依存します。 デフォルトでは、Py_TRACE_REFS は定義されておらず、 PyObject_HEAD は以下のコードに展開されます:
    int ob_refcnt;
    PyTypeObject *ob_type;
Py_TRACE_REFS が定義されている場合、以下のように展開 されます:
    PyObject *_ob_next, *_ob_prev;
    int ob_refcnt;
    PyTypeObject *ob_type;

PyObject_VAR_HEAD
マクロです。PyVarObject 型のフィールド宣言に展開されるマクロです; インスタンスによって可変の長さを持つオブジェクトを表現する新たな型を 宣言する場合に使います。マクロは常に以下のように展開されます:
    PyObject_HEAD
    int ob_size;
マクロ展開結果の一部にPyObject_HEAD が含まれており、 PyObject_HEAD の展開結果はPy_TRACE_REFS の定義に依存します。

PyObject_HEAD_INIT

PyCFunction
ほとんどの Python の呼び出し可能オブジェクトを C で実装する際に 用いられている関数の型です。 この型の関数は二つの PyObject* 型パラメタをとり、 PyObject* 型の値を返します。戻り値を NULLにする場合、 例外をセットしておかなければなりません。NULLでない値を返す場合、 戻り値は Python に関数の戻り値として公開される値として解釈されます。 この型の関数は新たな参照を返さなければなりません。

PyMethodDef
拡張型のメソッドを記述する際に用いる構造体です。この構造体には 4 つのフィールドがあります:

フィールド C データ型 意味
ml_name char * メソッド名
ml_meth PyCFunction C 実装へのポインタ
ml_flags int 呼び出しをどのように行うかを示すフラグビット
ml_doc char * docstring の内容を指すポインタ

ml_meth は C の関数ポインタです。関数は別の型で定義 されていてもかまいませんが、常に PyObject* を返します。 関数が PyFunction でない場合、メソッドテーブル内でキャスト を行うようコンパイラが要求することになるでしょう。 PyCFunction では最初のパラメタがPyObject* 型で あると定義していますが、固有の C 型を self オブジェクトに 使う実装はよく行われています。

ml_flags フィールドはビットフィールドで、以下のフラグが入ります。 個々のフラグは呼び出し規約 (calling convention) や束縛規約 (binding convention) を表します。 呼び出し規約フラグでは、METH_VARARGS および METH_KEYWORDS を組み合わせられます (ただし、 METH_KEYWORDS 単体の指定を行っても METH_VARARGS | METH_KEYWORDS と 同じなので注意してください)。 呼び出し規約フラグは束縛フラグと組み合わせられます。

METH_VARARGS
PyCFunction 型のメソッドで典型的に使われる呼び出し規約です。 関数はPyObject* 型の引数値を二つ要求します。最初の引数は メソッドの self オブジェクトです; モジュール関数の場合、 Py_InitModule4() に与えることになる値が入ります (NULL にするとPy_InitModule() が使われます)。 第二のパラメタ (よく args と呼ばれます) は、全ての引数を 表現するタプルオブジェクトです。パラメタは通常、 PyArg_ParseTuple()PyArg_UnpackTuple で処理されます。

METH_KEYWORDS
このフラグを持つメソッドはPyCFunctionWithKeywords 型でなければなりません。PyCFunctionWithKeywords は 三つのパラメタ:selfargs、 およびキーワード引数 全てからなる辞書、を要求します。このフラグは通常 METH_VARARGS と組み合わされ、パラメタは PyArg_ParseTupleAndKeywords() で処理されます。

METH_NOARGS
引数のないメソッドは、METH_NOARGS フラグをつけた場合、 必要な引数が指定されているかをチェックしなくなります。 こうしたメソッドは PyCFunction 型でなくてはなりません。 オブジェクトのメソッドに使った場合、第一のパラメタは self になり、オブジェクトインスタンスへの参照を保持することになります。 いずれにせよ、第二のパラメタは NULLになります。

METH_O
単一のオブジェクト引数だけをとるメソッドは、 PyArg_ParseTuple() を引数 "O" にして呼び出す代わりに、 METH_O フラグつきで指定できます。メソッドは PyCFunction 型で、self パラメタと単一の引数を表現する PyObject* パラメタを伴います。

METH_OLDARGS
この呼び出し規約は撤廃されました。メソッドはPyCFunction 型で なければなりません。第二引数は、引数がない場合には NULL、単一の 引数の場合にはその引数オブジェクト、複数個の引数の場合には引数 オブジェクトからなるタプルです。この呼び出し規約を使うと、複数個の 引数の場合と、単一のタプルが唯一引数の場合を区別できなくなってしまいます。

以下の二つの定数は、呼び出し規約を示すものではなく、 クラスのメソッドとして使う際の束縛方式を示すものです。 モジュールに対して定義された関数で用いてはなりません。 メソッドに対しては、最大で一つしかこのフラグをセットできません。

METH_CLASS
メソッドの最初の引数には、型のインスタンスではなく型オブジェクト が渡されます。このフラグは 組み込み関数 classmethod()を使って生成するのと同じクラスメソッド (class method) を生成するために使われます。 バージョン 2.3 で 新たに追加 された仕様です。

METH_STATIC
メソッドの最初の引数には、型のインスタンスではなく NULL が 渡されます。このフラグは、 staticmethod() を使って生成するのと同じ静的メソッド (static method) を生成するために使われます。 バージョン 2.3 で 新たに追加 された仕様です。

もう一つの定数は、あるメソッドを同名の別のメソッド定義と置き換えるか どうかを制御します。

METH_COEXIST
メソッドを既存の定義を置き換える形でロードします。 METH_COEXIST を指定しなければ、デフォルトの設定にしたがって、 定義が重複しないようスキップします。スロットラッパはメソッドテーブル よりも前にロードされるので、例えば sq_contains スロットは ラップしているメソッド __contains__() を生成し、同名の PyCFunction のロードを阻止します。このフラグを定義すると、 PyCFunction はラッパオブジェクトを置き換える形でロードされ、 スロットと連立します。 PyCFunctions の呼び出しはラッパオブジェクトの 呼び出しよりも最適化されているので、こうした仕様が便利になります。 バージョン 2.4 で 新たに追加 された仕様です。

PyObject* Py_FindMethod(PyMethodDef table[], PyObject *ob, char *name)
戻り値: 新たな参照.
C で実装された拡張型の束縛メソッドオブジェクトを返します。 PyObject_GenericGetAttr() 関数を使わない tp_getattrotp_getattr ハンドラを実装する際に 便利です。

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。