Python では、オブジェクト型を定義する上で数多くの構造体が使われます。この節では三つの構造体とその利用方法について説明します。
全ての Python オブジェクトは、オブジェクトのメモリ内表現の先頭部分にある少数のフィールドを完全に共有しています。このフィールドは PyObject および PyVarObject 型で表現されます。 PyObject 型や PyVarObject 型もまた、他の全ての Python オブジェクトを定義する上で直接的・間接的に使われているマクロを使って定義されています。
全てのオブジェクト型はこの型を拡張したものです。この型には、あるオブジェクトに対するオブジェクトとしてのポインタを Python から扱う必要がある際に必要な情報が入っています。通常に “リリースされている” ビルドでは、この構造体にはオブジェクトの参照カウントと、オブジェクトに対応する型オブジェクトだけが入っています。
PyObject_HEAD マクロ展開で定義されているフィールドに対応します。
PyObject を拡張して、 ob_size フィールドを追加したものです。この構造体は、 長さ (length) の概念を持つオブジェクトだけに対して使います。この型が Python/C API で使われることはほとんどありません。 PyObject_VAR_HEAD マクロ展開で定義されているフィールドに対応します。
PyObject および PyVarObject の定義には以下のマクロが使われています:
PyObject 型のフィールド宣言に展開されるマクロです; 可変でない長さを持つオブジェクトを表現する新たな型を宣言する場合に使います。展開によってどのフィールドが宣言されるかは、 Py_TRACE_REFS の定義に依存します。デフォルトでは、 Py_TRACE_REFS は定義されておらず、 PyObject_HEAD は以下のコードに展開されます:
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;
Py_TRACE_REFS が定義されている場合、以下のように展開されます:
PyObject *_ob_next, *_ob_prev;
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;
マクロです。 PyVarObject 型のフィールド宣言に展開されるマクロです; インスタンスによって可変の長さを持つオブジェクトを表現する新たな型を宣言する場合に使います。マクロは常に以下のように展開されます:
PyObject_HEAD
Py_ssize_t ob_size;
マクロ展開結果の一部に PyObject_HEAD が含まれており、 PyObject_HEAD の展開結果は Py_TRACE_REFS の定義に依存します。
新しい PyObject 型のための初期値に展開するマクロです。このマクロは次のように展開されます。
_PyObject_EXTRA_INIT
1, type,
新しい、 ob_size フィールドを含む PyVarObject 型のための初期値に展開するマクロです。このマクロは次のように展開されます。
_PyObject_EXTRA_INIT
1, type, size,
ほとんどの Python の呼び出し可能オブジェクトを C で実装する際に用いられている関数の型です。この型の関数は二つの PyObject* 型パラメタをとり、 PyObject* 型の値を返します。戻り値を NULL にする場合、例外をセットしておかなければなりません。 NULL でない値を返す場合、戻り値は Python に関数の戻り値として公開される値として解釈されます。この型の関数は新たな参照を返さなければなりません。
拡張型のメソッドを記述する際に用いる構造体です。この構造体には 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 と同じなので注意してください)。呼び出し規約フラグは束縛フラグと組み合わせられます。
PyCFunction 型のメソッドで典型的に使われる呼び出し規約です。関数は PyObject* 型の引数値を二つ要求します。最初の引数はメソッドの self オブジェクトです; モジュール関数の場合、これはモジュールオブジェクトです。第二のパラメタ (よく args と呼ばれます) は、全ての引数を表現するタプルオブジェクトです。パラメタは通常、 PyArg_ParseTuple() や PyArg_UnpackTuple() で処理されます。
このフラグを持つメソッドは PyCFunctionWithKeywords 型でなければなりません。 PyCFunctionWithKeywords は三つのパラメタ:self 、 args 、およびキーワード引数全てからなる辞書、を要求します。このフラグは通常 METH_VARARGS と組み合わされ、パラメタは PyArg_ParseTupleAndKeywords() で処理されます。
引数のないメソッドは、 METH_NOARGS フラグをつけた場合、必要な引数が指定されているかをチェックしなくなります。こうしたメソッドは PyCFunction 型でなくてはなりません。第一のパラメタは self になり、モジュールかオブジェクトインスタンスへの参照を保持することになります。いずれにせよ、第二のパラメタは NULL になります。
単一のオブジェクト引数だけをとるメソッドは、 PyArg_ParseTuple() を引数 "O" にして呼び出す代わりに、 METH_O フラグつきで指定できます。メソッドは PyCFunction 型で、 self パラメタと単一の引数を表現する PyObject* パラメタを伴います。
この呼び出し規約は撤廃されました。メソッドは PyCFunction 型でなければなりません。第二引数は、引数がない場合には NULL 、単一の引数の場合にはその引数オブジェクト、複数個の引数の場合には引数オブジェクトからなるタプルです。この呼び出し規約を使うと、複数個の引数の場合と、単一のタプルが唯一引数の場合を区別できなくなってしまいます。
以下の二つの定数は、呼び出し規約を示すものではなく、クラスのメソッドとして使う際の束縛方式を示すものです。モジュールに対して定義された関数で用いてはなりません。メソッドに対しては、最大で一つしかこのフラグをセットできません。
メソッドの最初の引数には、型のインスタンスではなく型オブジェクトが渡されます。このフラグは組み込み関数 classmethod() を使って生成するのと同じ クラスメソッド (class method) を生成するために使われます。
バージョン 2.3 で追加.
メソッドの最初の引数には、型のインスタンスではなく NULL が渡されます。このフラグは、 staticmethod() を使って生成するのと同じ 静的メソッド (static method) を生成するために使われます。
バージョン 2.3 で追加.
もう一つの定数は、あるメソッドを同名の別のメソッド定義と置き換えるかどうかを制御します。
メソッドを既存の定義を置き換える形でロードします。 METH_COEXIST を指定しなければ、デフォルトの設定にしたがって、定義が重複しないようスキップします。スロットラッパはメソッドテーブルよりも前にロードされるので、例えば sq_contains スロットはラップしているメソッド __contains__() を生成し、同名の PyCFunction のロードを阻止します。このフラグを定義すると、 PyCFunction はラッパオブジェクトを置き換える形でロードされ、スロットと連立します。 PyCFunctions の呼び出しはラッパオブジェクトの呼び出しよりも最適化されているので、こうした仕様が便利になります。
バージョン 2.4 で追加.
type の C 構造体のメンバとして格納されている、ある型の属性を表す構造体です。この構造体のフィールドは以下のとおりです:
フィールド | C の型 | 意味 |
---|---|---|
name | char * | メンバ名 |
type | int | C 構造体の中のメンバの型 |
offset | Py_ssize_t | そのメンバの type object 構造体中の場所の offset バイト数 |
flags | int | フィールドが読み込み専用か書込み可能なのかを示すビットフラグ |
doc | char * | docstring の内容へのポインタ |
type はたくさんのCの型を意味する T_ マクロのうちの1つです。メンバが Python からアクセスされるとき、そのメンバは対応する Python の型に変換されます。
マクロ名 | Cの型 |
---|---|
T_SHORT | short |
T_INT | int |
T_LONG | long |
T_FLOAT | float |
T_DOUBLE | double |
T_STRING | char * |
T_OBJECT | PyObject * |
T_OBJECT_EX | PyObject * |
T_CHAR | char |
T_BYTE | char |
T_UBYTE | unsigned char |
T_UINT | unsigned int |
T_USHORT | unsigned short |
T_ULONG | unsigned long |
T_BOOL | char |
T_LONGLONG | long long |
T_ULONGLONG | unsigned long long |
T_PYSSIZET | Py_ssize_t |
T_OBJECT と T_OBJECT_EX については、 T_OBJECT がメンバが NULL だったときに None を返すのに対し、 T_OBJECT_EX は AttributeError を発生させる点が異なります。 T_OBJECT_EX は属性に対する del 文をより正しくあつかうので、できれば T_OBJECT よりも T_OBJECT_EX を使ってください。
flags には読み書きアクセス可能なら 0 で、読み込み専用なら READONLY を設定します。 type に T_STRING を使うと、強制的に READONLY 扱いになります。 T_OBJECT and T_OBJECT_EX メンバだけが del 可能です。 (NULL が代入されます).
C で実装された拡張型の束縛メソッドオブジェクトを返します。 PyObject_GenericGetAttr() 関数を使わない tp_getattro や tp_getattr ハンドラを実装する際に便利です。