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_OFFSET flag. To get the actual number of positional arguments from nargsf, use PyVectorcall_NARGS().

  • kwnames はキーワード引数の名前を含むタプルです。

    言い換えると、kwargs 辞書のキーです。 名前は文字列 (str またはそのサブクラスのインスタンス) で、重複してはいけません。 キーワード引数がない場合、kwnames は 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

args

kwargs

PyObject_Call()

PyObject *

tuple

dict/NULL

PyObject_CallNoArgs()

PyObject *

---

---

PyObject_CallOneArg()

PyObject *

1 個のオブジェクト

---

PyObject_CallObject()

PyObject *

tuple/NULL

---

PyObject_CallFunction()

PyObject *

format

---

PyObject_CallMethod()

obj + char*

format

---

PyObject_CallFunctionObjArgs()

PyObject *

可変長引数

---

PyObject_CallMethodObjArgs()

obj + 名前

可変長引数

---

PyObject_CallMethodNoArgs()

obj + 名前

---

---

PyObject_CallMethodOneArg()

obj + 名前

1 個のオブジェクト

---

PyObject_Vectorcall()

PyObject *

vectorcall

vectorcall

PyObject_VectorcallDict()

PyObject *

vectorcall

dict/NULL

PyObject_VectorcallMethod()

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 を返します。この関数呼び出しは常に成功します。