Call プロトコル¶
CPython は tp_call と vectorcall の二つの呼び出しプロトコルをサポートしています。
tp_call プロトコル¶
tp_call を設定したクラスのインスタンスは呼び出し可能です。
このスロットのシグネチャは次のとおりです。
PyObject *tp_call(PyObject *callable, PyObject *args, PyObject *kwargs);
Python コードの callable(*args, **kwargs) と同様に、位置引数のタプルとキーワード引数の辞書を使って呼び出します。
args は NULL であってはいけません (引数がなければ空のタプルを使います)。
ただし、キーワード引数がなければ kwargs は NULL で構いません。
この規約は tp_call だけでなく、tp_new と tp_init で引数を渡すときにも使います。
オブジェクトを呼び出すには PyObject_Call() または別の 呼び出し API を使ってください。
vectorcall プロトコル¶
Added in version 3.9.
vectorcall プロトコルは、呼び出しを効率化するための追加のプロトコルとして PEP 590 で導入されました。
目安として、呼び出し可能オブジェクトが vectorcall をサポートしていれば、CPython は内部の呼び出しでそれを優先します。
ただし、厳密な規則ではありません。
また、サードパーティの拡張の中には PyObject_Call() を使わずに tp_call を直接使うものもあります。
そのため、vectorcall をサポートするクラスは tp_call も実装する必要があります。
さらに、どちらのプロトコルでも同じ動作をしなければなりません。
これを実現するために推奨される方法は、tp_call を PyVectorcall_Call() に設定することです。
繰り返しますが、次の点が重要です。
警告
vectorcall をサポートするクラスは、同じ意味を持つ tp_call も 必ず 実装しなければなりません。
バージョン 3.12 で変更: クラスの __call__() メソッドが再代入されると、そのクラスから Py_TPFLAGS_HAVE_VECTORCALL フラグを取り除くようになりました。
(この再代入は内部で tp_call だけを設定するため、vectorcall 関数と動作が異なる可能性があります。)
以前の Python では、vectorcall は 不変な型 または静的な型でのみ使うべきです。
tp_call より遅くなる場合、クラスは vectorcall を実装すべきではありません。 例えば、呼び出される側が結局引数を args タプルと kwargs 辞書に変換する必要があるなら、vectorcall を実装する意味はありません。
クラスは Py_TPFLAGS_HAVE_VECTORCALL フラグを有効にし、tp_vectorcall_offset をオブジェクト構造体内の vectorcallfunc の位置のオフセットに設定することで、vectorcall プロトコルを実装できます。
これは次のシグネチャを持つ関数へのポインタです。
-
typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- 次に属します: Stable ABI (バージョン 3.12 より).
callableは呼び出されるオブジェクトです。args is a C array consisting of the positional arguments followed by the values of the keyword arguments. This can be NULL if there are no arguments.
nargsf is the number of positional arguments plus possibly the
PY_VECTORCALL_ARGUMENTS_OFFSETflag. To get the actual number of positional arguments from nargsf, usePyVectorcall_NARGS().kwnames is a tuple containing the names of the keyword arguments; in other words, the keys of the kwargs dict. These names must be strings (instances of
stror a subclass) and they must be unique. If there are no keyword arguments, then kwnames can instead be NULL.
-
PY_VECTORCALL_ARGUMENTS_OFFSET¶
- 次に属します: Stable ABI (バージョン 3.12 より).
vectorcall の
nargsf引数にこのフラグが設定されている場合、呼び出される側は一時的にargs[-1]を変更できます。 つまり、argsは割り当てられたベクトル内の引数 0 ではなく引数 1 を指します。 呼び出される側は、戻る前にargs[-1]の値を元に戻す必要があります。PyObject_VectorcallMethod()の場合、このフラグは代わりにargs[0]を変更してよいことを意味します。追加の割り当てなしに低コストで設定できる場合、呼び出し側は
PY_VECTORCALL_ARGUMENTS_OFFSETを使うことが推奨されます。 これにより、束縛メソッドなどの呼び出し可能オブジェクトは、先頭にself引数を追加して次の呼び出しを行う処理を非常に効率的に実行できます。Added in version 3.8.
vectorcall を実装するオブジェクトを呼び出すには、ほかの呼び出し可能オブジェクトと同様に 呼び出し API の関数を使ってください。
通常は PyObject_Vectorcall() が最も効率的です。
再帰の管理¶
tp_call を使う場合、呼び出される側は 再帰 を管理する必要はありません。
CPython は tp_call による呼び出しで Py_EnterRecursiveCall() と Py_LeaveRecursiveCall() を使います。
効率のため、vectorcall による呼び出しではこの管理を行いません。
必要に応じて、呼び出される側が Py_EnterRecursiveCall() と Py_LeaveRecursiveCall() を使ってください。
vectorcall サポート API¶
-
Py_ssize_t PyVectorcall_NARGS(size_t nargsf)¶
- 次に属します: Stable ABI (バージョン 3.12 より).
vectorcall の
nargsf引数から、実際の引数の数を返します。 現在は次と同等です。(Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)
ただし、将来の拡張に対応するため、関数
PyVectorcall_NARGSを使ってください。Added in version 3.8.
-
vectorcallfunc PyVectorcall_Function(PyObject *op)¶
opが vectorcall プロトコルをサポートしていなければ (型がサポートしていない場合も、そのインスタンスがサポートしていない場合も)NULLを返します。 それ以外の場合は、opに格納された vectorcall 関数ポインタを返します。 この関数が例外を送出することはありません。主に、
opが vectorcall をサポートするかどうかを確認するのに便利です。PyVectorcall_Function(op) != NULLで確認できます。Added in version 3.9.
-
PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)¶
- 次に属します: Stable ABI (バージョン 3.12 より).
それぞれタプルと辞書で与えられた位置引数とキーワード引数を使い、
callableのvectorcallfuncを呼び出します。この特殊用途の関数は、
tp_callスロットに設定するか、tp_callの実装内で使うためのものです。Py_TPFLAGS_HAVE_VECTORCALLフラグを確認せず、tp_callへのフォールバックも行いません。Added in version 3.8.
オブジェクト呼び出し API¶
Python オブジェクトを呼び出すためのさまざまな関数があります。 各関数は、呼び出すオブジェクトがサポートする tp_call または vectorcall の規約に引数を変換します。 変換を最小限にするため、手元のデータの形式に最も合う関数を選んでください。
利用できる関数を以下の表にまとめます。 詳細は個別の説明を参照してください。
関数 |
callable |
|
|
|---|---|---|---|
|
tuple |
dict/ |
|
|
--- |
--- |
|
|
1 個のオブジェクト |
--- |
|
|
tuple/ |
--- |
|
|
format |
--- |
|
obj + |
format |
--- |
|
|
可変長引数 |
--- |
|
obj + 名前 |
可変長引数 |
--- |
|
obj + 名前 |
--- |
--- |
|
obj + 名前 |
1 個のオブジェクト |
--- |
|
|
vectorcall |
vectorcall |
|
|
vectorcall |
dict/ |
|
arg + 名前 |
vectorcall |
vectorcall |
-
PyObject *PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI.
呼び出し可能な Python のオブジェクト callable を、タプル args として与えられる引数と辞書 kwargs として与えられる名前付き引数とともに呼び出します。
argsはNULLであってはいけません。 引数が不要な場合は空のタプルを使ってください。 キーワード引数が不要な場合はkwargsをNULLにできます。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
これは次の Python の式と同等です:
callable(*args, **kwargs)。
-
PyObject *PyObject_CallNoArgs(PyObject *callable)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI (バージョン 3.10 より).
呼び出し可能な Python オブジェクト
callableを引数なしで呼び出します。 引数なしで呼び出すには最も効率的な方法です。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
Added in version 3.9.
-
PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg)¶
- 戻り値: 新しい参照。
呼び出し可能な Python オブジェクト
callableを、位置引数argだけを渡し、キーワード引数なしで呼び出します。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
Added in version 3.9.
-
PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI.
呼び出し可能な Python オブジェクト
callableを、タプルargsで与えられた引数で呼び出します。 引数が不要な場合はargsをNULLにできます。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
これは次の Python の式と同等です:
callable(*args)。
-
PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI.
呼び出し可能な Python オブジェクト callable を可変数個の C 引数とともに呼び出します。 C 引数は
Py_BuildValue()形式のフォーマット文字列を使って記述します。 format は NULL かもしれず、与える引数がないことを表します。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
これは次の Python の式と同等です:
callable(*args)。PyObject* args だけを引数に渡す場合は、
PyObject_CallFunctionObjArgs()がより速い方法であることを覚えておいてください。バージョン 3.4 で変更: format の型が
char *から変更されました。
-
PyObject *PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI.
オブジェクト obj の name という名前のメソッドを、いくつかの C 引数とともに呼び出します。 C 引数はタプルを生成する
Py_BuildValue()形式のフォーマット文字列で記述されています。format は NULL でもよく、引数が与えられないことを表します。
成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
これは次の Python の式と同等です:
obj.name(arg1, arg2, ...)。PyObject* args だけを引数に渡す場合は、
PyObject_CallMethodObjArgs()がより速い方法であることを覚えておいてください。バージョン 3.4 で変更: name と format の型が
char *から変更されました。
-
PyObject *PyObject_CallFunctionObjArgs(PyObject *callable, ...)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI.
呼び出し可能な Python オブジェクト callable を可変数個の PyObject* 引数とともに呼び出します。引数列は末尾に NULL がついた可変数個のパラメタとして与えます。
成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
これは次の Python の式と同等です:
callable(arg1, arg2, ...)。
-
PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)¶
- 戻り値: 新しい参照。 次に属します: Stable ABI.
Python オブジェクト obj のメソッドを呼び出します、メソッド名は Python 文字列オブジェクト name で与えます。可変数個の PyObject* 引数と共に呼び出されます. 引数列は末尾に NULL がついた可変数個のパラメタとして与えます。
成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
-
PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)¶
Python オブジェクト
objのメソッドを引数なしで呼び出します。 メソッド名は Python 文字列オブジェクトnameで指定します。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
Added in version 3.9.
-
PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)¶
Python オブジェクト
objのメソッドを、一つの位置引数argを渡して呼び出します。 メソッド名は Python 文字列オブジェクトnameで指定します。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
Added in version 3.9.
-
PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- 次に属します: Stable ABI (バージョン 3.12 より).
呼び出し可能な Python オブジェクト
callableを呼び出します。 引数はvectorcallfuncと同じです。callableが vectorcall をサポートしている場合は、callableに格納された vectorcall 関数を直接呼び出します。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
Added in version 3.8:
_PyObject_Vectorcallとして追加。バージョン 3.9 で変更: 先頭のアンダースコアを取り除いた現在の名前に変更しました。 以前の暫定的な名前は 緩やかに非推奨 です。
-
PyObject *PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)¶
位置引数は vectorcall プロトコルとまったく同じ方法で渡し、キーワード引数は辞書
kwdictで渡してcallableを呼び出します。args配列には位置引数だけを含めます。内部でどちらのプロトコルを使っても、引数の変換が必要です。 そのため、この関数は呼び出し側がキーワード引数の辞書をすでに用意していて、位置引数のタプルは持っていない場合だけに使ってください。
Added in version 3.9.
-
PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- 次に属します: Stable ABI (バージョン 3.12 より).
vectorcall の呼び出し規約でメソッドを呼び出します。 メソッド名は Python 文字列
nameで指定します。 メソッドを呼び出す対象のオブジェクトはargs[0]で、args[1]から始まるargs配列が呼び出しの引数を表します。 位置引数は少なくとも一つ必要です。nargsfはargs[0]を含む位置引数の数で、args[0]の値を一時的に変更してよい場合はPY_VECTORCALL_ARGUMENTS_OFFSETを加えます。 キーワード引数はPyObject_Vectorcall()と同じ方法で渡せます。オブジェクトが
Py_TPFLAGS_METHOD_DESCRIPTORの機能を持つ場合、argsベクトル全体を引数として非束縛メソッドオブジェクトを呼び出します。成功したら呼び出しの結果を返し、失敗したら例外を送出し NULL を返します。
Added in version 3.9.
呼び出しサポート API¶
-
int PyCallable_Check(PyObject *o)¶
- 次に属します: Stable ABI.
オブジェクト o が呼び出し可能オブジェクトかどうか調べます。オブジェクトが呼び出し可能であるときに
1を返し、そうでないときには0を返します。この関数呼び出しは常に成功します。