タイプオブジェクト
おそらく、Pythonオブジェクトシステムの最も重要な構造の1つは、新しい型を定義する構造、 PyTypeObject 構造です。 型オブジェクトは、PyObject_*()
またはPyType_*()
関数のいずれかを使用して処理できますが、ほとんどのPythonアプリケーションにとって興味深いものはあまりありません。 これらのオブジェクトは、オブジェクトの動作の基本であるため、インタープリター自体および新しいタイプを実装する拡張モジュールにとって非常に重要です。
型オブジェクトは、ほとんどの標準型と比較してかなり大きいです。 サイズの理由は、各型オブジェクトが多数の値、主にC関数ポインターを格納し、それぞれが型の機能のごく一部を実装するためです。 このセクションでは、タイプオブジェクトのフィールドについて詳しく説明します。 フィールドは、構造内で発生する順序で説明されます。
Typedef:unaryfunc、binaryfunc、ternaryfunc、inquiry、coercion、intargfunc、intintargfunc、intobjargproc、intintobjargproc、objobjargproc、destructor、freefunc、printfunc、getattrfunc、getattrofunc、setattrfunc、setattrofunc、cmpfunc、
PyTypeObject の構造定義は、Include/object.h
にあります。 参照の便宜のために、これはそこで見つかった定義を繰り返します。
typedef struct _typeobject {
PyObject_VAR_HEAD
char *tp_name; /* For printing, in format "<module>.<name>" */
int tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
long tp_flags;
char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
long tp_weaklistoffset;
/* Added in release 2.2 */
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
long tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
} PyTypeObject;
タイプオブジェクト構造は、 PyVarObject 構造を拡張します。 ob_size
フィールドは、動的型に使用されます(type_new()
によって作成され、通常はクラスステートメントから呼び出されます)。 PyType_Type (メタタイプ)は tp_itemsize を初期化することに注意してください。これは、そのインスタンス(つまり、 タイプオブジェクト) must にはob_size
フィールドが必要です。
- PyObject *PyObject._ob_next
PyObject *PyObject._ob_prev
これらのフィールドは、マクロ
Py_TRACE_REFS
が定義されている場合にのみ存在します。 NULL への初期化は、PyObject_HEAD_INIT
マクロによって処理されます。 静的に割り当てられたオブジェクトの場合、これらのフィールドは常に NULL のままです。 動的に割り当てられたオブジェクトの場合、これら2つのフィールドは、ヒープ上のすべてのライブオブジェクトの二重リンクリストにオブジェクトをリンクするために使用されます。 これは、さまざまなデバッグ目的に使用できます。 現在のところ、唯一の用途は、環境変数 PYTHONDUMPREFS が設定されている場合に、実行の終了時にまだ生きているオブジェクトを印刷することです。これらのフィールドはサブタイプに継承されません。
- Py_ssize_t PyObject.ob_refcnt
これは、
PyObject_HEAD_INIT
マクロによって1
に初期化されたタイプオブジェクトの参照カウントです。 静的に割り当てられた型オブジェクトの場合、型のインスタンス(ob_type
が型を指すオブジェクト)はではなくは参照としてカウントされることに注意してください。 ただし、動的に割り当てられた型オブジェクトの場合、インスタンス do は参照としてカウントされます。このフィールドはサブタイプに継承されません。
バージョン2.5で変更:このフィールドは以前は
int
タイプでした。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。
- PyTypeObject *PyObject.ob_type
これはタイプのタイプ、つまりメタタイプです。
PyObject_HEAD_INIT
マクロへの引数によって初期化され、その値は通常&PyType_Type
である必要があります。 ただし、(少なくとも)Windowsで使用可能でなければならない動的にロード可能な拡張モジュールの場合、コンパイラーは、これが有効なイニシャライザーではないと文句を言います。 したがって、慣例では、 NULL をPyObject_HEAD_INIT
マクロに渡し、モジュールの初期化関数の開始時に、他の処理を行う前にこのフィールドを明示的に初期化します。 これは通常、次のように行われます。Foo_Type.ob_type = &PyType_Type;
これは、タイプのインスタンスを作成する前に実行する必要があります。 PyType_Ready()は、
ob_type
が NULL であるかどうかを確認し、そうである場合は初期化します。Python2.2では、&PyType_Type
に設定されます。 Python 2.2.1以降では、基本クラスのob_type
フィールドに初期化されます。 PyType_Ready()は、このフィールドがゼロ以外の場合、このフィールドを変更しません。Python 2.2では、このフィールドはサブタイプに継承されません。 2.2.1以降、2.3以降では、サブタイプに継承されます。
- Py_ssize_t PyVarObject.ob_size
静的に割り当てられた型オブジェクトの場合、これはゼロに初期化する必要があります。 動的に割り当てられたタイプオブジェクトの場合、このフィールドには特別な内部的な意味があります。
このフィールドはサブタイプに継承されません。
- char *PyTypeObject.tp_name
タイプの名前を含むNULで終了する文字列へのポインタ。 モジュールグローバルとしてアクセス可能な型の場合、文字列は完全なモジュール名、ドット、型名の順にする必要があります。 組み込み型の場合は、型名だけにする必要があります。 モジュールがパッケージのサブモジュールである場合、完全なパッケージ名は完全なモジュール名の一部です。 たとえば、パッケージ
P
のサブパッケージQ
のモジュールM
で定義されたT
という名前の型には、 tp_name イニシャライザー"P.Q.M.T"
。動的に割り当てられた型オブジェクトの場合、これは型名であり、型dictにキー
'__module__'
の値として明示的に格納されているモジュール名である必要があります。静的に割り当てられたタイプのオブジェクトの場合、tp_nameフィールドにはドットが含まれている必要があります。 最後のドットの前のすべてが
__module__
属性としてアクセス可能になり、最後のドットの後のすべてが __ name __ 属性としてアクセス可能になります。ドットが存在しない場合、 tp_name フィールド全体が __ name __ 属性としてアクセス可能になり、
__module__
属性は未定義です(辞書で明示的に設定されていない限り、上で説明した)。 これはあなたのタイプが酸洗いすることが不可能になることを意味します。 また、pydocで作成されたモジュールのドキュメントには記載されていません。このフィールドはサブタイプに継承されません。
- Py_ssize_t PyTypeObject.tp_basicsize
Py_ssize_t PyTypeObject.tp_itemsize
これらのフィールドを使用すると、タイプのインスタンスのサイズをバイト単位で計算できます。
タイプには2種類あります。固定長のインスタンスを持つタイプにはゼロ tp_itemsize フィールドがあり、可変長のインスタンスを持つタイプにはゼロ以外の tp_itemsize フィールドがあります。 固定長のインスタンスを持つタイプの場合、 tp_basicsize で指定されているように、すべてのインスタンスのサイズは同じです。
可変長インスタンスを持つタイプの場合、インスタンスには
ob_size
フィールドが必要であり、インスタンスサイズは tp_basicsize に tp_itemsize のN倍を加えたものです。ここで、Nは「オブジェクトの長さ」。 Nの値は通常、インスタンスのob_size
フィールドに格納されます。 例外があります。たとえば、長いintは負のob_size
を使用して負の数を示し、Nはabs(ob_size)
です。 また、インスタンスレイアウトにob_size
フィールドが存在するからといって、インスタンス構造が可変長であることを意味するわけではありません(たとえば、リストタイプの構造には固定長のインスタンスがありますが、これらのインスタンスには意味のあるob_size
フィールド)。基本サイズには、マクロ PyObject_HEAD または PyObject_VAR_HEAD (インスタンス構造体の宣言に使用される方)によって宣言されたインスタンスのフィールドが含まれ、これには
_ob_prev
が含まれます。および_ob_next
フィールド(存在する場合)。 つまり、 tp_basicsize の初期化子を取得する唯一の正しい方法は、インスタンスレイアウトの宣言に使用される構造体でsizeof
演算子を使用することです。 基本サイズにはGCヘッダーサイズは含まれていません(これはPython 2.2の新機能です。2.1および2.0では、GCヘッダーサイズは tp_basicsize に含まれていました)。これらのフィールドは、サブタイプによって個別に継承されます。 基本タイプにゼロ以外の tp_itemsize がある場合、サブタイプで tp_itemsize を別のゼロ以外の値に設定することは一般的に安全ではありません(ただし、これは基本タイプ)。
配置に関する注意:変数アイテムに特定の配置が必要な場合は、 tp_basicsize の値で処理する必要があります。 例:型が
double
の配列を実装するとします。 tp_itemsize はsizeof(double)
です。 tp_basicsize がsizeof(double)
の倍数であるのはプログラマーの責任です(これがdouble
の配置要件であると想定)。
- destructor PyTypeObject.tp_dealloc
インスタンスデストラクタ関数へのポインタ。 この関数は、インスタンスが割り当て解除されないことが型によって保証されていない限り、定義する必要があります(シングルトン
None
およびEllipsis
の場合のように)。デストラクタ関数は、新しい参照カウントがゼロのときに Py_DECREF()および Py_XDECREF()マクロによって呼び出されます。 この時点で、インスタンスはまだ存在していますが、それへの参照はありません。 デストラクタ関数は、インスタンスが所有するすべての参照を解放し、インスタンスが所有するすべてのメモリバッファを解放し(バッファの割り当てに使用される割り当て関数に対応する解放関数を使用)、最後に(最後のアクションとして)型の[X270X ] tp_free 関数。 タイプがサブタイプ化できない場合( Py_TPFLAGS_BASETYPE フラグビットが設定されていない場合)、 tp_free を介さずに、オブジェクトのデアロケーターを直接呼び出すことができます。 オブジェクトのデロケーターは、インスタンスの割り当てに使用されるものである必要があります。 これは通常、 PyObject_New()または
PyObject_VarNew()
を使用してインスタンスが割り当てられた場合は PyObject_Del()、インスタンスが割り当てられた場合は PyObject_GC_Del()です。 PyObject_GC_New()または PyObject_GC_NewVar()を使用します。このフィールドはサブタイプに継承されます。
- printfunc PyTypeObject.tp_print
インスタンスの印刷関数へのオプションのポインタ。
print関数は、インスタンスが real ファイルに出力された場合にのみ呼び出されます。 疑似ファイル( StringIO インスタンスなど)に出力されると、インスタンスの tp_repr または tp_str 関数が呼び出されて文字列に変換されます。 これらは、タイプの tp_print フィールドが NULL の場合にも呼び出されます。 タイプは、 tp_repr または tp_str とは異なる出力を生成する方法で tp_print を実装してはなりません。
印刷関数は、 PyObject_Print()と同じ署名で呼び出されます:
int tp_print(PyObject *self, FILE *file, int flags)
。 self 引数は、出力されるインスタンスです。 file 引数は、印刷先のstdioファイルです。 flags 引数は、フラグビットで構成されます。 現在定義されている唯一のフラグビットはPy_PRINT_RAW
です。Py_PRINT_RAW
フラグビットが設定されている場合、インスタンスは tp_str がフォーマットするのと同じ方法で出力する必要があります。Py_PRINT_RAW
フラグビットがクリアされている場合、インスタンスは tp_repr がフォーマットするのと同じように出力する必要があります。 比較中にエラーが発生した場合は、-1
を返し、例外条件を設定する必要があります。tp_print フィールドが非推奨になる可能性があります。 いずれの場合も、 tp_print を定義するのではなく、 tp_repr と tp_str を使用して印刷することをお勧めします。
このフィールドはサブタイプに継承されます。
- getattrfunc PyTypeObject.tp_getattr
get-attribute-string関数へのオプションのポインター。
このフィールドは非推奨です。 定義するときは、 tp_getattro 関数と同じように機能する関数を指す必要がありますが、属性名を指定するためにPython文字列オブジェクトの代わりにC文字列を使用します。 署名は
PyObject * tp_getattr(PyObject *o, char *attr_name);
このフィールドは、 tp_getattro とともにサブタイプによって継承されます。サブタイプの tp_getattr および tp_getattro は両方とも NULL です。
- setattrfunc PyTypeObject.tp_setattr
属性を設定および削除するための関数へのオプションのポインタ。
このフィールドは非推奨です。 定義するときは、 tp_setattro 関数と同じように機能する関数を指す必要がありますが、属性名を指定するためにPython文字列オブジェクトの代わりにC文字列を使用します。 署名は
PyObject * tp_setattr(PyObject *o, char *attr_name, PyObject *v);
v 引数を NULL に設定して、属性を削除します。 このフィールドは、 tp_setattro とともにサブタイプに継承されます。サブタイプの tp_setattr および tp_setattro は両方とも NULL です。
- cmpfunc PyTypeObject.tp_compare
三者比較関数へのオプションのポインター。
署名は PyObject_Compare()の場合と同じです。 この関数は、 self が other より大きい場合は
1
を返し、 self が other [と等しい場合は0
を返す必要があります。 X131X]、および self が other よりも小さい場合は-1
。 比較中にエラーが発生した場合は、-1
を返し、例外条件を設定する必要があります。このフィールドは、 tp_richcompare および tp_hash とともにサブタイプに継承されます。サブタイプは tp_compare 、 tp_richcompare 、およびの3つすべてを継承します。サブタイプの tp_compare 、 tp_richcompare 、および tp_hash がすべて NULL の場合のtp_hash 。
- reprfunc PyTypeObject.tp_repr
組み込み関数 repr()を実装する関数へのオプションのポインター。
署名は PyObject_Repr()の場合と同じです。 文字列またはUnicodeオブジェクトを返す必要があります。 理想的には、この関数は、 eval()に渡されたときに、適切な環境が与えられたときに同じ値のオブジェクトを返す文字列を返す必要があります。 これが不可能な場合は、
'<'
で始まり、'>'
で終わる文字列を返す必要があります。この文字列から、オブジェクトのタイプと値の両方を推測できます。このフィールドが設定されていない場合、
<%s object at %p>
の形式の文字列が返されます。ここで、%s
は型名に置き換えられ、%p
はオブジェクトのメモリアドレスに置き換えられます。このフィールドはサブタイプに継承されます。
- PyNumberMethods *tp_as_number
番号プロトコルを実装するオブジェクトにのみ関連するフィールドを含む追加の構造体へのポインター。 これらのフィールドは、 Number Object Structures に記載されています。
tp_as_number
フィールドは継承されませんが、含まれているフィールドは個別に継承されます。
- PySequenceMethods *tp_as_sequence
シーケンスプロトコルを実装するオブジェクトにのみ関連するフィールドを含む追加の構造体へのポインタ。 これらのフィールドは、シーケンスオブジェクト構造に記載されています。
tp_as_sequence
フィールドは継承されませんが、含まれているフィールドは個別に継承されます。
- PyMappingMethods *tp_as_mapping
マッピングプロトコルを実装するオブジェクトにのみ関連するフィールドを含む追加の構造体へのポインタ。 これらのフィールドは、マッピングオブジェクト構造に記載されています。
tp_as_mapping
フィールドは継承されませんが、含まれているフィールドは個別に継承されます。
- hashfunc PyTypeObject.tp_hash
組み込み関数 hash()を実装する関数へのオプションのポインター。
署名は PyObject_Hash()の場合と同じです。 Clongを返す必要があります。 値
-1
は通常の戻り値として返されるべきではありません。 ハッシュ値の計算中にエラーが発生した場合、関数は例外を設定して-1
を返す必要があります。このフィールドを明示的に PyObject_HashNotImplemented()に設定して、親タイプからのハッシュメソッドの継承をブロックできます。 これは、Pythonレベルで
__hash__ = None
と同等であると解釈され、isinstance(o, collections.Hashable)
はFalse
を正しく返します。 逆もまた真であることに注意してください。Pythonレベルのクラスで__hash__ = None
を設定すると、tp_hash
スロットが PyObject_HashNotImplemented()に設定されます。このフィールドが設定されていない場合、2つの可能性があります。 tp_compare フィールドと tp_richcompare フィールドが両方とも NULL の場合、オブジェクトのアドレスに基づくデフォルトのハッシュ値が返されます。 ; それ以外の場合は、
TypeError
が発生します。このフィールドは、 tp_richcompare および tp_compare とともにサブタイプに継承されます。サブタイプは tp_compare 、 tp_richcompare 、およびの3つすべてを継承します。 tp_hash 、サブタイプの tp_compare 、 tp_richcompare 、および tp_hash がすべて NULL の場合。
- ternaryfunc PyTypeObject.tp_call
オブジェクトの呼び出しを実装する関数へのオプションのポインター。 オブジェクトが呼び出せない場合、これは NULL である必要があります。 署名は PyObject_Call()の場合と同じです。
このフィールドはサブタイプに継承されます。
- reprfunc PyTypeObject.tp_str
組み込み操作 str()を実装する関数へのオプションのポインター。 ( str は現在型であり、 str()はその型のコンストラクターを呼び出すことに注意してください。 このコンストラクターは PyObject_Str()を呼び出して実際の作業を行い、 PyObject_Str()はこのハンドラーを呼び出します。)
署名は PyObject_Str()の場合と同じです。 文字列またはUnicodeオブジェクトを返す必要があります。 この関数は、オブジェクトの「わかりやすい」文字列表現を返す必要があります。これは、printステートメントで使用される表現であるためです。
このフィールドが設定されていない場合、 PyObject_Repr()が呼び出され、文字列表現が返されます。
このフィールドはサブタイプに継承されます。
- getattrofunc PyTypeObject.tp_getattro
get-attribute関数へのオプションのポインター。
署名は PyObject_GetAttr()の場合と同じです。 通常、このフィールドを PyObject_GenericGetAttr()に設定すると便利です。これは、オブジェクト属性を検索する通常の方法を実装します。
このフィールドは、 tp_getattr とともにサブタイプに継承されます。サブタイプの tp_getattr および tp_getattro は両方とも NULL です。
- setattrofunc PyTypeObject.tp_setattro
属性を設定および削除するための関数へのオプションのポインタ。
署名は PyObject_SetAttr()の場合と同じですが、属性を削除するには v を NULL に設定する必要があります。 通常、このフィールドを PyObject_GenericSetAttr()に設定すると便利です。これは、オブジェクト属性を設定する通常の方法を実装します。
このフィールドは、 tp_setattr とともにサブタイプに継承されます。サブタイプの tp_setattr および tp_setattro は両方とも NULL です。
- PyBufferProcs *PyTypeObject.tp_as_buffer
バッファインターフェイスを実装するオブジェクトにのみ関連するフィールドを含む追加の構造体へのポインタ。 これらのフィールドは、バッファオブジェクト構造に記載されています。
tp_as_buffer フィールドは継承されませんが、含まれているフィールドは個別に継承されます。
- long PyTypeObject.tp_flags
このフィールドは、さまざまなフラグのビットマスクです。 一部のフラグは、特定の状況でのバリアントセマンティクスを示します。 その他は、型オブジェクト(または
tp_as_number
、tp_as_sequence
、tp_as_mapping
、および tp_as_buffer を介して参照される拡張構造)の特定のフィールドを示すために使用されます。歴史的に常に存在するとは限らなかったものが有効です。 そのようなフラグビットがクリアされている場合、それが保護するタイプフィールドにアクセスしてはならず、代わりにゼロまたは NULL 値を持っていると見なす必要があります。このフィールドの継承は複雑です。 ほとんどのフラグビットは個別に継承されます。 基本タイプにフラグビットが設定されている場合、サブタイプはこのフラグビットを継承します。 拡張構造が継承される場合、拡張構造に関連するフラグビットは厳密に継承されます。 フラグビットの基本型の値は、拡張構造へのポインタとともにサブタイプにコピーされます。 Py_TPFLAGS_HAVE_GC フラグビットは、 tp_traverse および tp_clear フィールドと一緒に継承されます。 Py_TPFLAGS_HAVE_GC フラグビットがサブタイプでクリアされ、サブタイプの tp_traverse および tp_clear フィールドが存在する場合( Py_TPFLAGS_HAVE_RICHCOMPARE [X199フラグビット)であり、 NULL 値を持ちます。
現在、次のビットマスクが定義されています。 これらは、
|
演算子を使用してOR演算し、 tp_flags フィールドの値を形成できます。 マクロ PyType_HasFeature()は、型とフラグの値 tp と f を受け取り、tp->tp_flags & f
がゼロ以外かどうかをチェックします。- Py_TPFLAGS_HAVE_GETCHARBUFFER
このビットが設定されている場合、 tp_as_buffer によって参照される PyBufferProcs 構造体には
bf_getcharbuffer
フィールドがあります。
- Py_TPFLAGS_HAVE_SEQUENCE_IN
このビットが設定されている場合、
tp_as_sequence
によって参照される PySequenceMethods 構造体にはsq_contains
フィールドがあります。
- Py_TPFLAGS_GC
このビットは廃止されました。 名前を付けるために使用されていたビットは、もう使用されていません。 これで、シンボルはゼロとして定義されます。
- Py_TPFLAGS_HAVE_INPLACEOPS
このビットが設定されている場合、
tp_as_sequence
によって参照される PySequenceMethods 構造体とtp_as_number
によって参照される PyNumberMethods 構造体にはインプレース演算子のフィールドが含まれます。 特に、これは、 PyNumberMethods 構造にフィールドnb_inplace_add
、nb_inplace_subtract
、nb_inplace_multiply
、nb_inplace_divide
、 [ X133X]、nb_inplace_power
、nb_inplace_lshift
、nb_inplace_rshift
、nb_inplace_and
、nb_inplace_xor
、およびnb_inplace_or
; PySequenceMethods 構造体には、フィールドsq_inplace_concat
およびsq_inplace_repeat
があります。
- Py_TPFLAGS_CHECKTYPES
このビットが設定されている場合、
tp_as_number
によって参照される PyNumberMethods 構造体のバイナリおよび三項演算は、任意のオブジェクトタイプの引数を受け入れ、必要に応じて独自のタイプ変換を行います。 このビットがクリアされている場合、これらの操作では、すべての引数の型として現在の型が必要であり、呼び出し元は最初に強制操作を実行することになっています。 これは、nb_add
、nb_subtract
、nb_multiply
、nb_divide
、nb_remainder
、nb_divmod
、nb_power
に適用されます。 ]、nb_lshift
、nb_rshift
、nb_and
、nb_xor
、およびnb_or
。
- Py_TPFLAGS_HAVE_RICHCOMPARE
このビットが設定されている場合、タイプオブジェクトには tp_richcompare フィールドと、 tp_traverse および tp_clear フィールドがあります。
- Py_TPFLAGS_HAVE_WEAKREFS
このビットが設定されている場合、 tp_weaklistoffset フィールドが定義されます。 タイプの tp_weaklistoffset フィールドの値がゼロより大きい場合、タイプのインスタンスは弱く参照可能です。
- Py_TPFLAGS_HAVE_ITER
このビットが設定されている場合、タイプオブジェクトには tp_iter フィールドと tp_iternext フィールドがあります。
- Py_TPFLAGS_HAVE_CLASS
このビットが設定されている場合、タイプオブジェクトには、Python 2.2以降で定義されたいくつかの新しいフィールドがあります: tp_methods 、 tp_members 、 tp_getset 、 tp_base 、 tp_dict 、 tp_descr_get 、 tp_descr_set 、 tp_dictoffset 、 tp_init 、 tp_alloc 、[ X296X] tp_new 、 tp_free 、 tp_is_gc 、 tp_bases 、 tp_mro 、 tp_cache 、 tp_subclasses 、および tp_weaklist 。
- Py_TPFLAGS_HEAPTYPE
このビットは、型オブジェクト自体がヒープに割り当てられるときに設定されます。 この場合、そのインスタンスの
ob_type
フィールドは型への参照と見なされ、型オブジェクトは新しいインスタンスが作成されるとINCREFされ、インスタンスが破棄されるとDECREFされます(これにより、サブタイプのインスタンスには適用されません。インスタンスのob_typeによって参照されるタイプのみがINCREFまたはDECREFされます)。
- Py_TPFLAGS_BASETYPE
このビットは、そのタイプを別のタイプの基本タイプとして使用できる場合にセットされます。 このビットがクリアされている場合、型をサブタイプ化することはできません(Javaの「final」クラスと同様)。
- Py_TPFLAGS_READY
このビットは、タイプオブジェクトが PyType_Ready()によって完全に初期化されたときに設定されます。
- Py_TPFLAGS_READYING
このビットは、 PyType_Ready()が型オブジェクトを初期化する過程で設定されます。
- Py_TPFLAGS_HAVE_GC
このビットは、オブジェクトがガベージコレクションをサポートしている場合に設定されます。 このビットが設定されている場合、インスタンスは PyObject_GC_New()を使用して作成し、 PyObject_GC_Del()を使用して破棄する必要があります。 詳細については、セクションサイクリックガベージコレクションのサポートを参照してください。 このビットは、GC関連のフィールド tp_traverse および tp_clear が型オブジェクトに存在することも意味します。 ただし、これらのフィールドは、 Py_TPFLAGS_HAVE_GC がクリアされているが、 Py_TPFLAGS_HAVE_RICHCOMPARE が設定されている場合にも存在します。
- Py_TPFLAGS_DEFAULT
これは、型オブジェクトとその拡張構造内の特定のフィールドの存在に関連するすべてのビットのビットマスクです。 現在、次のビットが含まれています: Py_TPFLAGS_HAVE_GETCHARBUFFER 、 Py_TPFLAGS_HAVE_SEQUENCE_IN 、 Py_TPFLAGS_HAVE_INPLACEOPS 、 Py ] Py_TPFLAGS_HAVE_ITER 、および Py_TPFLAGS_HAVE_CLASS 。
- char *PyTypeObject.tp_doc
この型オブジェクトのdocstringを与えるNULで終了するC文字列へのオプションのポインタ。 これは、タイプおよびタイプのインスタンスの
__doc__
属性として公開されます。このフィールドは、サブタイプによって継承されたではありません。
次の3つのフィールドは、 Py_TPFLAGS_HAVE_RICHCOMPARE フラグビットが設定されている場合にのみ存在します。
- traverseproc PyTypeObject.tp_traverse
ガベージコレクターのトラバーサル関数へのオプションのポインター。 これは、 Py_TPFLAGS_HAVE_GC フラグビットが設定されている場合にのみ使用されます。 Pythonのガベージコレクションスキームの詳細については、セクション Cyclic GarbageCollectionのサポートを参照してください。
tp_traverse ポインターは、参照サイクルを検出するためにガベージコレクターによって使用されます。 tp_traverse 関数の一般的な実装では、Pythonオブジェクトであるインスタンスの各メンバーで Py_VISIT()を呼び出すだけです。 たとえば、これは thread 拡張モジュールの関数
local_traverse()
です。static int local_traverse(localobject *self, visitproc visit, void *arg) { Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dict); return 0; }
Py_VISIT()は、参照サイクルに参加できるメンバーでのみ呼び出されることに注意してください。
self->key
メンバーもありますが、 NULL またはPython文字列のみであるため、参照サイクルの一部にすることはできません。一方、メンバーがサイクルの一部になることは決してないことがわかっている場合でも、デバッグの補助として、 gc モジュールの get_referents()とにかくそのメンバーにアクセスすることをお勧めします。関数にはそれが含まれます。
Py_VISIT()では、
local_traverse()
の visit および arg パラメーターにこれらの特定の名前を付ける必要があることに注意してください。 それらに何も名前を付けないでください。このフィールドは、 tp_clear および Py_TPFLAGS_HAVE_GC フラグビットとともにサブタイプによって継承されます。フラグビット、 tp_traverse 、および tp_clear はすべて継承されます。サブタイプおよびですべてゼロの場合、基本タイプから、サブタイプには Py_TPFLAGS_HAVE_RICHCOMPARE フラグビットが設定されています。
- inquiry PyTypeObject.tp_clear
ガベージコレクターのclear関数へのオプションのポインター。 これは、 Py_TPFLAGS_HAVE_GC フラグビットが設定されている場合にのみ使用されます。
tp_clear メンバー関数は、ガベージコレクターによって検出された循環ガベージの参照サイクルを中断するために使用されます。 まとめると、システム内のすべての tp_clear 関数を組み合わせて、すべての参照サイクルを中断する必要があります。 これは微妙であり、疑わしい場合は tp_clear 関数を指定してください。 たとえば、タプルタイプは tp_clear 関数を実装していません。これは、参照サイクルを完全にタプルで構成できないことを証明できるためです。 したがって、他のタイプの tp_clear 関数は、タプルを含むサイクルを中断するのに十分でなければなりません。 これはすぐには明らかではなく、 tp_clear の実装を避ける正当な理由はめったにありません。
tp_clear の実装では、次の例のように、Pythonオブジェクトである可能性のあるメンバーの参照へのインスタンスの参照を削除し、それらのメンバーへのポインターを NULL に設定する必要があります。
static int local_clear(localobject *self) { Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }
参照のクリアはデリケートであるため、 Py_CLEAR()マクロを使用する必要があります。含まれるオブジェクトへのポインターが NULL に設定されるまで、含まれるオブジェクトへの参照をデクリメントしないでください。 これは、参照カウントを減らすと、含まれているオブジェクトがゴミ箱になり、任意のPythonコードの呼び出しを含む一連の再生アクティビティがトリガーされる可能性があるためです(含まれているオブジェクトに関連付けられているファイナライザーまたはweakrefコールバックが原因)。 そのようなコードが self を再度参照できる場合は、その時点で含まれているオブジェクトへのポインタが NULL であり、 self が含まれていることを認識できるようにすることが重要です。オブジェクトは使用できなくなりました。 Py_CLEAR()マクロは、安全な順序で操作を実行します。
tp_clear 関数の目的は参照サイクルを中断することであるため、参照サイクルに参加できないPython文字列やPython整数などの含まれているオブジェクトをクリアする必要はありません。 一方、含まれているすべてのPythonオブジェクトをクリアし、タイプの tp_dealloc 関数を記述して tp_clear を呼び出すと便利な場合があります。
Pythonのガベージコレクションスキームの詳細については、セクション Cyclic GarbageCollectionのサポートを参照してください。
このフィールドは、 tp_traverse および Py_TPFLAGS_HAVE_GC フラグビットとともにサブタイプによって継承されます。フラグビット、 tp_traverse 、および tp_clear はすべて継承されます。サブタイプおよびですべてゼロの場合、基本タイプから、サブタイプには Py_TPFLAGS_HAVE_RICHCOMPARE フラグビットが設定されています。
- richcmpfunc PyTypeObject.tp_richcompare
署名が
PyObject *tp_richcompare(PyObject *a, PyObject *b, int op)
であるリッチ比較関数へのオプションのポインター。関数は比較の結果を返す必要があります(通常は
Py_True
またはPy_False
)。 比較が未定義の場合はPy_NotImplemented
を返す必要があり、別のエラーが発生した場合はNULL
を返し、例外条件を設定する必要があります。ノート
限られた比較のセットだけが意味をなすタイプを実装したい場合(例:
==
と!=
は、<
とその仲間ではなく、豊富な比較機能でTypeError
を直接上げます。このフィールドは、 tp_compare および tp_hash とともにサブタイプに継承されます。サブタイプは tp_compare 、 tp_richcompare 、およびの3つすべてを継承します。 tp_hash 、サブタイプの tp_compare 、 tp_richcompare 、および tp_hash がすべて NULL の場合。
次の定数は、 tp_richcompare および PyObject_RichCompare()の3番目の引数として使用されるように定義されています。
絶え間ない
比較
Py_LT
<
Py_LE
<=
Py_EQ
==
Py_NE
!=
Py_GT
>
Py_GE
>=
次のフィールドは、 Py_TPFLAGS_HAVE_WEAKREFS フラグビットが設定されている場合にのみ存在します。
- long PyTypeObject.tp_weaklistoffset
このタイプのインスタンスが弱参照可能である場合、このフィールドはゼロより大きく、弱参照リストヘッドのインスタンス構造にオフセットが含まれます(GCヘッダーが存在する場合は無視されます)。 このオフセットは、
PyObject_ClearWeakRefs()
およびPyWeakref_*()
関数によって使用されます。 インスタンス構造には、 NULL に初期化されるタイプPyObject*
のフィールドを含める必要があります。このフィールドを tp_weaklist と混同しないでください。 これは、型オブジェクト自体への弱参照のリストヘッドです。
このフィールドはサブタイプに継承されますが、以下のルールを参照してください。 サブタイプはこのオフセットをオーバーライドできます。 これは、サブタイプが基本タイプとは異なる弱参照リストヘッドを使用することを意味します。 リストヘッドは常に tp_weaklistoffset を介して検出されるため、これは問題にはなりません。
クラスステートメントで定義された型に
__slots__
宣言がなく、その基本型のいずれも弱参照可能でない場合、インスタンスレイアウトに弱参照リストのヘッドスロットを追加し、[そのスロットのオフセットのX243X] tp_weaklistoffset 。タイプの __ slots __ 宣言に
__weakref__
という名前のスロットが含まれている場合、そのスロットはタイプのインスタンスの弱参照リストヘッドになり、スロットのオフセットはタイプの tp_weaklistoffset [に格納されます。 X219X]。型の __ slots __ 宣言に
__weakref__
という名前のスロットが含まれていない場合、型はその tp_weaklistoffset を基本型から継承します。
次の2つのフィールドは、 Py_TPFLAGS_HAVE_ITER フラグビットが設定されている場合にのみ存在します。
- getiterfunc PyTypeObject.tp_iter
オブジェクトのイテレータを返す関数へのオプションのポインタ。 その存在は通常、このタイプのインスタンスが反復可能であることを示します(ただし、シーケンスはこの関数なしで反復可能であり、クラシックインスタンスは
__iter__()
メソッドを定義していなくても、常にこの関数を持っています)。この関数には、 PyObject_GetIter()と同じ署名があります。
このフィールドはサブタイプに継承されます。
- iternextfunc PyTypeObject.tp_iternext
イテレータ内の次の項目を返す関数へのオプションのポインタ。 イテレータが使い果たされると、 NULL を返す必要があります。
StopIteration
例外が設定される場合と設定されない場合があります。 別のエラーが発生した場合は、 NULL も返す必要があります。 その存在は通常、このタイプのインスタンスがイテレータであることを示します(ただし、 next()メソッドを定義していなくても、クラシックインスタンスには常にこの関数があります)。イテレータ型は tp_iter 関数も定義する必要があり、その関数は(新しいイテレータインスタンスではなく)イテレータインスタンス自体を返す必要があります。
この関数には、 PyIter_Next()と同じ署名があります。
このフィールドはサブタイプに継承されます。
tp_weaklist までの次のフィールドは、 Py_TPFLAGS_HAVE_CLASS フラグビットが設定されている場合にのみ存在します。
- struct PyMethodDef *PyTypeObject.tp_methods
このタイプの通常のメソッドを宣言する、 PyMethodDef 構造体の静的 NULL で終了する配列へのオプションのポインター。
配列内のエントリごとに、メソッド記述子を含むエントリがタイプのディクショナリに追加されます(以下の tp_dict を参照)。
このフィールドはサブタイプに継承されません(メソッドは別のメカニズムを介して継承されます)。
- struct PyMemberDef *PyTypeObject.tp_members
このタイプのインスタンスの通常のデータメンバー(フィールドまたはスロット)を宣言する、 PyMemberDef 構造体の静的 NULL で終了する配列へのオプションのポインター。
配列内のエントリごとに、メンバー記述子を含むエントリがタイプのディクショナリに追加されます(以下の tp_dict を参照)。
このフィールドはサブタイプに継承されません(メンバーは別のメカニズムを介して継承されます)。
- struct PyGetSetDef *PyTypeObject.tp_getset
このタイプのインスタンスの計算された属性を宣言する、 PyGetSetDef 構造の静的 NULL で終了する配列へのオプションのポインター。
配列内のエントリごとに、getset記述子を含むエントリがタイプのディクショナリに追加されます(以下の tp_dict を参照)。
このフィールドはサブタイプに継承されません(計算された属性は別のメカニズムを介して継承されます)。
- PyTypeObject *PyTypeObject.tp_base
タイププロパティが継承される基本タイプへのオプションのポインタ。 このレベルでは、単一の継承のみがサポートされます。 多重継承では、メタタイプを呼び出して型オブジェクトを動的に作成する必要があります。
このフィールドは(明らかに)サブタイプに継承されませんが、デフォルトで
&PyBaseObject_Type
(Pythonプログラマーにはタイプオブジェクトとして知られています)になります。
- PyObject *PyTypeObject.tp_dict
タイプの辞書は、 PyType_Ready()によってここに保存されます。
このフィールドは通常、PyType_Readyが呼び出される前に、 NULL に初期化する必要があります。 タイプの初期属性を含むディクショナリに初期化することもできます。 PyType_Ready()が型を初期化すると、オーバーロードされた操作(
__add__()
など)に対応しない場合にのみ、型の追加属性をこのディクショナリに追加できます。このフィールドはサブタイプに継承されません(ただし、ここで定義されている属性は別のメカニズムを介して継承されます)。
- descrgetfunc PyTypeObject.tp_descr_get
「記述子get」関数へのオプションのポインター。
関数のシグネチャは
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
このフィールドはサブタイプに継承されます。
- descrsetfunc PyTypeObject.tp_descr_set
記述子の値を設定および削除するための関数へのオプションのポインター。
関数のシグネチャは
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
value 引数は、値を削除するために NULL に設定されます。 このフィールドはサブタイプに継承されます。
- long PyTypeObject.tp_dictoffset
このタイプのインスタンスにインスタンス変数を含むディクショナリがある場合、このフィールドはゼロ以外であり、インスタンス変数ディクショナリのタイプのインスタンスのオフセットが含まれます。 このオフセットは、 PyObject_GenericGetAttr()によって使用されます。
このフィールドを tp_dict と混同しないでください。 これは、タイプオブジェクト自体の属性の辞書です。
このフィールドの値がゼロより大きい場合は、インスタンス構造の先頭からのオフセットを指定します。 値がゼロ未満の場合は、インスタンス構造の end からのオフセットを指定します。 負のオフセットは使用するのに費用がかかるため、インスタンス構造に可変長の部分が含まれている場合にのみ使用する必要があります。 これは、たとえば、 str または tuple のサブタイプにインスタンス変数ディクショナリを追加するために使用されます。 tp_basicsize フィールドは、ディクショナリが基本オブジェクトレイアウトに含まれていない場合でも、その場合に最後に追加されたディクショナリを考慮する必要があることに注意してください。 ポインタサイズが4バイトのシステムでは、 tp_dictoffset を
-4
に設定して、辞書が構造体の最後にあることを示す必要があります。インスタンス内の実際のディクショナリオフセットは、次のように負の tp_dictoffset から計算できます。
dictoffset = tp_basicsize + abs(ob_size)*tp_itemsize + tp_dictoffset if dictoffset is not aligned on sizeof(void*): round up to sizeof(void*)
ここで、 tp_basicsize 、 tp_itemsize 、 tp_dictoffset は型オブジェクトから取得され、
ob_size
はインスタンスから取得されます。 long intはob_size
の符号を使用して数値の符号を格納するため、絶対値が使用されます。 (この計算を自分で行う必要はありません。_PyObject_GetDictPtr()
によって行われます。)このフィールドはサブタイプに継承されますが、以下のルールを参照してください。 サブタイプはこのオフセットをオーバーライドできます。 これは、サブタイプインスタンスが基本タイプとは異なるオフセットでディクショナリを格納することを意味します。 辞書は常に tp_dictoffset を介して検出されるため、これは問題にはなりません。
クラスステートメントで定義された型に
__slots__
宣言がなく、その基本型にインスタンス変数辞書がない場合、インスタンスレイアウトに辞書スロットが追加され、 tp_dictoffset が設定されます。そのスロットのオフセットに。クラスステートメントで定義された型に __ slots __ 宣言がある場合、その型はその tp_dictoffset を基本型から継承します。
( __ dict __ という名前のスロットを __ slots __ 宣言に追加しても、期待される効果はありません。混乱を招くだけです。 たぶん、これは
__weakref__
のような機能として追加する必要があります。)
- initproc PyTypeObject.tp_init
インスタンス初期化関数へのオプションのポインター。
この関数は、クラスの
__init__()
メソッドに対応します。__init__()
と同様に、__init__()
を呼び出さずにインスタンスを作成でき、__init__()
メソッドを再度呼び出すことでインスタンスを再初期化できます。関数のシグネチャは
int tp_init(PyObject *self, PyObject *args, PyObject *kwds)
self引数は、初期化されるインスタンスです。 args および kwds 引数は、
__init__()
の呼び出しの位置引数とキーワード引数を表します。tp_init 関数は、 NULL でない場合、型の tp_new 関数がその型のインスタンスを返した後、その型を呼び出すことによってインスタンスが正常に作成されたときに呼び出されます。タイプ。 tp_new 関数が、元のタイプのサブタイプではない他のタイプのインスタンスを返す場合、 tp_init 関数は呼び出されません。 tp_new が元のタイプのサブタイプのインスタンスを返す場合、サブタイプの tp_init が呼び出されます。 (バージョンノート:ここで説明するのは、Python2.2.1以降で実装されているものです。 Python 2.2では、 NULL でない場合でも、 tp_new によって返されるオブジェクトのタイプの tp_init が常に呼び出されていました。)
このフィールドはサブタイプに継承されます。
- allocfunc PyTypeObject.tp_alloc
インスタンス割り当て関数へのオプションのポインタ。
関数のシグネチャは
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems)
この関数の目的は、メモリ割り当てをメモリ初期化から分離することです。 インスタンスに適切な長さのメモリブロックへのポインタを返し、適切に配置され、ゼロに初期化されますが、
ob_refcnt
は1
に設定され、ob_type
はに設定されます。 type引数。 タイプの tp_itemsize がゼロ以外の場合、オブジェクトのob_size
フィールドは nitems に初期化され、割り当てられたメモリブロックの長さはtp_basicsize + nitems*tp_itemsize
である必要があります。 ]、sizeof(void*)
の倍数に切り上げられます。 それ以外の場合、 nitems は使用されず、ブロックの長さは tp_basicsize である必要があります。追加のメモリを割り当てるためであっても、他のインスタンスの初期化を行うためにこの関数を使用しないでください。 これは tp_new で行う必要があります。
このフィールドは静的サブタイプに継承されますが、動的サブタイプ(クラスステートメントによって作成されたサブタイプ)には継承されません。 後者の場合、このフィールドは常に PyType_GenericAlloc()に設定され、標準のヒープ割り当て戦略を強制します。 これは、静的に定義された型の推奨値でもあります。
- newfunc PyTypeObject.tp_new
インスタンス作成関数へのオプションのポインター。
この関数が特定のタイプに対して NULL である場合、そのタイプを呼び出して新しいインスタンスを作成することはできません。 おそらく、ファクトリ関数のように、インスタンスを作成する他の方法があります。
関数のシグネチャは
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
サブタイプ引数は、作成されるオブジェクトのタイプです。 args および kwds 引数は、型の呼び出しの位置引数とキーワード引数を表します。 サブタイプは、 tp_new 関数が呼び出されるタイプと同じである必要はないことに注意してください。 そのタイプのサブタイプである可能性があります(ただし、無関係のタイプではありません)。
tp_new 関数は、
subtype->tp_alloc(subtype, nitems)
を呼び出してオブジェクトにスペースを割り当て、絶対に必要なだけの初期化を実行する必要があります。 安全に無視または繰り返すことができる初期化は、 tp_init ハンドラーに配置する必要があります。 経験則として、不変型の場合、すべての初期化は tp_new で行う必要がありますが、可変型の場合、ほとんどの初期化は tp_init に延期する必要があります。このフィールドは、 tp_base が NULL または
&PyBaseObject_Type
である静的型によって継承されないことを除いて、サブタイプによって継承されます。 後者の例外は、Python2.2にリンクするだけで古い拡張タイプを呼び出せないようにするための予防策です。
- destructor PyTypeObject.tp_free
インスタンスの割り当て解除関数へのオプションのポインター。
この関数のシグネチャはわずかに変更されています。Python2.2および2.2.1では、そのシグネチャは
destructor
です。void tp_free(PyObject *)
Python 2.3以降では、その署名は
freefunc
です。void tp_free(void *)
両方のバージョンと互換性のある唯一のイニシャライザーは
_PyObject_Del
であり、その定義はPython2.3で適切に適合されています。このフィールドは静的サブタイプに継承されますが、動的サブタイプ(クラスステートメントによって作成されたサブタイプ)には継承されません。 後者の場合、このフィールドは、 PyType_GenericAlloc()と Py_TPFLAGS_HAVE_GC フラグビットの値を一致させるのに適したデアロケーターに設定されます。
- inquiry PyTypeObject.tp_is_gc
ガベージコレクターによって呼び出される関数へのオプションのポインター。
ガベージコレクターは、特定のオブジェクトが収集可能かどうかを知る必要があります。 通常は、オブジェクトのタイプの tp_flags フィールドを確認し、 Py_TPFLAGS_HAVE_GC フラグビットを確認するだけで十分です。 ただし、一部のタイプには静的に割り当てられたインスタンスと動的に割り当てられたインスタンスが混在しており、静的に割り当てられたインスタンスは収集できません。 このようなタイプは、この関数を定義する必要があります。 収集可能なインスタンスの場合は
1
を返し、収集不可能なインスタンスの場合は0
を返す必要があります。 署名はint tp_is_gc(PyObject *self)
(これの唯一の例はタイプ自体です。 メタタイプ PyType_Type は、静的に割り当てられたタイプと動的に割り当てられたタイプを区別するためにこの関数を定義します。)
このフィールドはサブタイプに継承されます。 (バージョンノート:Python 2.2では、継承されませんでした。 2.2.1以降のバージョンで継承されます。)
- PyObject *PyTypeObject.tp_bases
基本タイプのタプル。
これは、クラスステートメントによって作成された型に設定されます。 静的に定義された型の場合は、 NULL である必要があります。
このフィールドは継承されません。
- PyObject *PyTypeObject.tp_mro
メソッド解決順序で、タイプ自体で始まり、 object で終わる拡張された基本タイプのセットを含むタプル。
このフィールドは継承されません。 PyType_Ready()によって新たに計算されます。
- PyObject *PyTypeObject.tp_cache
- 未使用。 継承されません。 内部でのみ使用。
- PyObject *PyTypeObject.tp_subclasses
- サブクラスへの弱参照のリスト。 継承されません。 内部でのみ使用。
- PyObject *PyTypeObject.tp_weaklist
- この型オブジェクトへの弱参照の弱参照リストヘッド。 継承されません。 内部でのみ使用。
残りのフィールドは、機能テストマクロCOUNT_ALLOCS
が定義されている場合にのみ定義され、内部使用のみを目的としています。 それらは完全を期すためにここに文書化されています。 これらのフィールドはいずれもサブタイプに継承されません。 PYTHONSHOWALLOCCOUNT 環境変数を参照してください。
- Py_ssize_t PyTypeObject.tp_allocs
- 割り当ての数。
- Py_ssize_t PyTypeObject.tp_frees
- 無料の数。
- Py_ssize_t PyTypeObject.tp_maxalloc
- 同時に割り当てられるオブジェクトの最大数。
- PyTypeObject *PyTypeObject.tp_next
- ゼロ以外の tp_allocs フィールドを持つ次のタイプのオブジェクトへのポインター。
また、ガベージコレクションされたPythonでは、オブジェクトを作成したスレッドだけでなく、任意のPythonスレッドからtp_deallocを呼び出すことができます(オブジェクトがrefcountサイクルの一部になる場合、そのサイクルは、任意のガベージコレクションによって収集される可能性があります。スレッド)。 tp_deallocが呼び出されるスレッドがグローバルインタープリターロック(GIL)を所有するため、これはPythonAPI呼び出しの問題ではありません。 ただし、破棄されるオブジェクトが他のCまたはC ++ライブラリのオブジェクトを破棄する場合は、tp_deallocを呼び出したスレッドでそれらのオブジェクトを破棄しても、ライブラリの前提に違反しないように注意する必要があります。
番号オブジェクト構造
- type PyNumberMethods
この構造体は、オブジェクトが数値プロトコルを実装するために使用する関数へのポインターを保持します。 以下のほとんどすべての関数は、番号プロトコルセクションに記載されている同様の名前の関数によって使用されます。
構造の定義は次のとおりです。
typedef struct { binaryfunc nb_add; binaryfunc nb_subtract; binaryfunc nb_multiply; binaryfunc nb_divide; binaryfunc nb_remainder; binaryfunc nb_divmod; ternaryfunc nb_power; unaryfunc nb_negative; unaryfunc nb_positive; unaryfunc nb_absolute; inquiry nb_nonzero; /* Used by PyObject_IsTrue */ unaryfunc nb_invert; binaryfunc nb_lshift; binaryfunc nb_rshift; binaryfunc nb_and; binaryfunc nb_xor; binaryfunc nb_or; coercion nb_coerce; /* Used by the coerce() function */ unaryfunc nb_int; unaryfunc nb_long; unaryfunc nb_float; unaryfunc nb_oct; unaryfunc nb_hex; /* Added in release 2.0 */ binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; binaryfunc nb_inplace_divide; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; binaryfunc nb_inplace_rshift; binaryfunc nb_inplace_and; binaryfunc nb_inplace_xor; binaryfunc nb_inplace_or; /* Added in release 2.2 */ binaryfunc nb_floor_divide; binaryfunc nb_true_divide; binaryfunc nb_inplace_floor_divide; binaryfunc nb_inplace_true_divide; /* Added in release 2.5 */ unaryfunc nb_index; } PyNumberMethods;
バイナリ関数とターナリ関数は、フラグビット Py_TPFLAGS_CHECKTYPES に応じて、異なる種類の引数を受け取る場合があります。
- Py_TPFLAGS_CHECKTYPES が設定されていない場合、関数の引数はオブジェクトの型であることが保証されます。 呼び出し元は、
nb_coerce
メンバーによって指定された強制メソッドを呼び出して、引数を変換する責任があります。- coercion PyNumberMethods.nb_coerce
- coercion PyNumberMethods.nb_coerce
- この関数は PyNumber_CoerceEx()によって使用され、同じ署名を持っています。 最初の引数は常に、定義されたタイプのオブジェクトへのポインターです。 一般的な「より大きな」タイプへの変換が可能な場合、関数はポインターを変換されたオブジェクトへの新しい参照に置き換え、
0
を返します。 変換できない場合、関数は1
を返します。 エラー条件が設定されている場合は、-1
を返します。
- この関数は PyNumber_CoerceEx()によって使用され、同じ署名を持っています。 最初の引数は常に、定義されたタイプのオブジェクトへのポインターです。 一般的な「より大きな」タイプへの変換が可能な場合、関数はポインターを変換されたオブジェクトへの新しい参照に置き換え、
- Py_TPFLAGS_CHECKTYPES フラグが設定されている場合、バイナリ関数とターナリ関数はすべてのオペランドの型をチェックし、必要な変換を実装する必要があります(オペランドの少なくとも1つは定義された型のインスタンスです)。 これが推奨される方法です。 Python 3では、強制は完全になくなります。
指定されたオペランドに対して演算が定義されていない場合、2進関数と3進関数はPy_NotImplemented
を返す必要があり、別のエラーが発生した場合はNULL
を返して例外を設定する必要があります。
オブジェクト構造のマッピング
- type PyMappingMethods
- この構造体は、オブジェクトがマッピングプロトコルを実装するために使用する関数へのポインタを保持します。 3つのメンバーがあります。
- lenfunc PyMappingMethods.mp_length
- この関数は PyMapping_Length()と PyObject_Size()によって使用され、同じ署名を持っています。 オブジェクトの長さが定義されていない場合、このスロットは NULL に設定できます。
- binaryfunc PyMappingMethods.mp_subscript
- この関数は PyObject_GetItem()によって使用され、同じ署名を持っています。 PyMapping_Check()関数が
1
を返すには、このスロットを埋める必要があります。それ以外の場合は、 NULL にすることができます。
- objobjargproc PyMappingMethods.mp_ass_subscript
- この関数は、 PyObject_SetItem()および PyObject_DelItem()によって使用されます。 PyObject_SetItem()と同じ署名がありますが、 v を NULL に設定してアイテムを削除することもできます。 このスロットが NULL の場合、オブジェクトはアイテムの割り当てと削除をサポートしていません。
シーケンスオブジェクトの構造
- type PySequenceMethods
- この構造体は、オブジェクトがシーケンスプロトコルを実装するために使用する関数へのポインタを保持します。
- lenfunc PySequenceMethods.sq_length
- この関数は PySequence_Size()と PyObject_Size()によって使用され、同じ署名を持っています。
- binaryfunc PySequenceMethods.sq_concat
- この関数は PySequence_Concat()によって使用され、同じ署名を持っています。
nb_add
スロットを介して数値加算を試みた後、+
オペレーターによっても使用されます。
- ssizeargfunc PySequenceMethods.sq_repeat
- この関数は PySequence_Repeat()によって使用され、同じ署名を持っています。
nb_multiply
スロットを介して数値の乗算を試みた後、*
オペレーターによっても使用されます。
- ssizeargfunc PySequenceMethods.sq_item
この関数は PySequence_GetItem()によって使用され、同じ署名を持っています。 PySequence_Check()関数が
1
を返すには、このスロットを埋める必要があります。それ以外の場合は、 NULL にすることができます。負のインデックスは次のように処理されます。
sq_length
スロットがいっぱいになると、それが呼び出され、シーケンス長を使用してsq_item
に渡される正のインデックスが計算されます。sq_length
が NULL の場合、インデックスはそのまま関数に渡されます。
- ssizeobjargproc PySequenceMethods.sq_ass_item
- この関数は PySequence_SetItem()によって使用され、同じ署名を持っています。 オブジェクトがアイテムの割り当てと削除をサポートしていない場合、このスロットは NULL のままにしておくことができます。
- objobjproc PySequenceMethods.sq_contains
- この関数は PySequence_Contains()で使用でき、同じ署名があります。 このスロットは NULL のままにしておくことができます。この場合、 PySequence_Contains()は、一致するものが見つかるまでシーケンスをトラバースするだけです。
- binaryfunc PySequenceMethods.sq_inplace_concat
- この関数は PySequence_InPlaceConcat()によって使用され、同じ署名を持っています。 最初のオペランドを変更して返す必要があります。
- ssizeargfunc PySequenceMethods.sq_inplace_repeat
- この関数は PySequence_InPlaceRepeat()によって使用され、同じ署名を持っています。 最初のオペランドを変更して返す必要があります。
バッファオブジェクトの構造
バッファインターフェイスは、オブジェクトが内部データをデータのチャンクのセットとして公開できるモデルをエクスポートします。各チャンクは、ポインタと長さのペアとして指定されます。 これらのチャンクはセグメントと呼ばれ、メモリ内で連続していないと見なされます。
オブジェクトがバッファインターフェイスをエクスポートしない場合、 PyTypeObject 構造体の tp_as_buffer メンバーは NULL である必要があります。 それ以外の場合、 tp_as_buffer は PyBufferProcs 構造体を指します。
ノート
PyTypeObject 構造体が0
ではなく tp_flags メンバーの値に Py_TPFLAGS_DEFAULT を使用することが非常に重要です。 これは、 PyBufferProcs 構造にbf_getcharbuffer
スロットが含まれていることをPythonランタイムに通知します。 古いバージョンのPythonにはこのメンバーがなかったため、古い拡張機能を使用する新しいPythonインタープリターは、使用する前にその存在をテストできる必要があります。
- type PyBufferProcs
バッファプロトコルの実装を定義する関数ポインタを保持するために使用される構造。
最初のスロットは
bf_getreadbuffer
で、タイプは readbufferproc です。 このスロットが NULL の場合、オブジェクトは内部データからの読み取りをサポートしていません。 これは無意味なので、実装者はこれを入力する必要がありますが、呼び出し元はスロットに NULL 以外の値が含まれていることをテストする必要があります。次のスロットは、タイプ writebufferproc の
bf_getwritebuffer
です。 オブジェクトが返されたバッファへの書き込みを許可しない場合、このスロットは NULL である可能性があります。3番目のスロットは
bf_getsegcount
で、タイプは segcountproc です。 このスロットは NULL であってはならず、オブジェクトに含まれるセグメントの数を呼び出し元に通知するために使用されます。 PyString_Type や PyBuffer_Type オブジェクトなどの単純なオブジェクトには、単一のセグメントが含まれています。最後のスロットは
bf_getcharbuffer
で、タイプは charbufferproc です。 このスロットは、 Py_TPFLAGS_HAVE_GETCHARBUFFER フラグがオブジェクトの PyTypeObject の tp_flags フィールドに存在する場合にのみ存在します。 このスロットを使用する前に、呼び出し元は PyType_HasFeature()関数を使用してスロットが存在するかどうかをテストする必要があります。 フラグが存在する場合、bf_getcharbuffer
は NULL である可能性があり、オブジェクトの内容を 8ビット文字として使用できないことを示します。 オブジェクトの内容を8ビット文字として解釈できない場合も、スロット関数でエラーが発生する可能性があります。 たとえば、オブジェクトが浮動小数点値を保持するように構成された配列である場合、呼び出し元がbf_getcharbuffer
を使用して8ビット文字のシーケンスをフェッチしようとすると、例外が発生する可能性があります。 内部バッファを「テキスト」としてエクスポートするというこの概念は、本質的にバイナリであるオブジェクトと、文字ベースのコンテンツを持つオブジェクトを区別するために使用されます。ノート
現在のポリシーでは、これらの文字はマルチバイト文字である可能性があると規定されているようです。 これは、 N のバッファサイズが、 N 文字が存在することを意味するわけではないことを意味します。
- Py_TPFLAGS_HAVE_GETCHARBUFFER
bf_getcharbuffer
スロットが既知であることを示すためにタイプ構造に設定されたフラグビット。 これが設定されているからといって、オブジェクトがバッファインターフェイスをサポートしていることや、bf_getcharbuffer
スロットが NULL 以外であることを示すものではありません。
- typedef Py_ssize_t (*readbufferproc)(PyObject *self, Py_ssize_t segment, void **ptrptr)
*ptrptr
内のバッファの読み取り可能なセグメントへのポインタを返します。 この関数は例外を発生させることができます。その場合、-1
を返す必要があります。 指定するセグメントはゼロまたは正である必要があり、bf_getsegcount
スロット関数によって返されるセグメントの数よりも厳密に少なくなければなりません。 成功すると、セグメントの長さを返し、*ptrptr
をそのメモリへのポインタに設定します。
- typedef Py_ssize_t (*writebufferproc)(PyObject *self, Py_ssize_t segment, void **ptrptr)
*ptrptr
の書き込み可能なメモリバッファへのポインタと、そのセグメントの長さを関数の戻り値として返します。 メモリバッファは、バッファセグメントセグメントに対応している必要があります。-1
を返し、エラー時に例外を設定する必要があります。TypeError
は、オブジェクトが読み取り専用バッファーのみをサポートする場合に発生する必要があり、SystemError
は、セグメントが存在しないセグメントを指定する場合に発生する必要があります。
- typedef Py_ssize_t (*segcountproc)(PyObject *self, Py_ssize_t *lenp)
- バッファを構成するメモリセグメントの数を返します。 lenp が NULL でない場合、実装は
*lenp
内のすべてのセグメントのサイズ(バイト単位)の合計を報告する必要があります。 関数は失敗できません。
- typedef Py_ssize_t (*charbufferproc)(PyObject *self, Py_ssize_t segment, char **ptrptr)
- ptrptr が設定されているセグメント segment のサイズを返します。
*ptrptr
はメモリバッファに設定されます。 エラー時に-1
を返します。