#概要
Pythonの構造を理解する助けとして、C APIのドキュメントを読み砕いていく。
#内容
##環境
Python 3.9 (CPython)に話を固定したいが、必ずしもそうはならない。
tree (コミット; ブランチ)
(↑ githubのリンク)
##int PyNumber_Check(PyObject *o)
###<概説>
o
がインデックス整数だった場合、1
を返す。
###<定義>
int
PyNumber_Check(PyObject *o)
{
if (o == NULL)
return 0;
PyNumberMethods *nb = Py_TYPE(o)->tp_as_number;
return nb && (nb->nb_index || nb->nb_int || nb->nb_float || PyComplex_Check(o));
}
(定義出典)
###<使用例>
if (PyNumber_Check(v)) {
(使用例出典)
##PyObject* PyNumber_Add(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
を加算した結果を返し、失敗するとNULL
を返す。
Pythonの式o1 + o2
と同じ。
###<定義>
PyObject *
PyNumber_Add(PyObject *v, PyObject *w)
{
PyObject *result = BINARY_OP1(v, w, NB_SLOT(nb_add), "+");
if (result != Py_NotImplemented) {
return result;
}
Py_DECREF(result);
PySequenceMethods *m = Py_TYPE(v)->tp_as_sequence;
if (m && m->sq_concat) {
result = (*m->sq_concat)(v, w);
assert(_Py_CheckSlotResult(v, "+", result != NULL));
return result;
}
return binop_type_error(v, w, "+");
}
(定義出典)
###<使用例>
upper = PyNumber_Add(length, lower);
(使用例出典)
##PyObject* PyNumber_Subtract(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
からo2
を減算した結果を返し、失敗するとNULL
を返す。
Python の式o1 - o2
と同じ。
###<定義>
BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")
(定義出典)
###<定義補足>
#define BINARY_FUNC(func, op, op_name) \
PyObject * \
func(PyObject *v, PyObject *w) { \
return binary_op(v, w, NB_SLOT(op), op_name); \
}
static PyObject *
binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
{
PyObject *result = BINARY_OP1(v, w, op_slot, op_name);
...
return result;
}
# define BINARY_OP1(v, w, op_slot, op_name) binary_op1(v, w, op_slot)
static PyObject *
binary_op1(PyObject *v, PyObject *w, const int op_slot
)
{
...
slotv = NB_BINOP(Py_TYPE(v)->tp_as_number, op_slot);
...
x = slotv(v, w);
assert(_Py_CheckSlotResult(v, op_name, x != NULL));
if (x != Py_NotImplemented) {
return x;
}
...
}
大筋を変えない程度に改変。
###<使用例>
newval = PyNumber_Subtract(lv, rv);
(使用例出典)
##PyObject* PyNumber_Multiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
を乗算した結果を返し、失敗するとNULL
を返す。
Pythonの式o1 * o2
と同じ。
###<定義>
PyObject *
PyNumber_Multiply(PyObject *v, PyObject *w)
{
PyObject *result = BINARY_OP1(v, w, NB_SLOT(nb_multiply), "*");
if (result == Py_NotImplemented) {
PySequenceMethods *mv = Py_TYPE(v)->tp_as_sequence;
PySequenceMethods *mw = Py_TYPE(w)->tp_as_sequence;
Py_DECREF(result);
if (mv && mv->sq_repeat) {
return sequence_repeat(mv->sq_repeat, v, w);
}
else if (mw && mw->sq_repeat) {
return sequence_repeat(mw->sq_repeat, w, v);
}
result = binop_type_error(v, w, "*");
}
return result;
}
(定義出典)
###<使用例>
return PyNumber_Multiply(v, w);
(使用例出典)
##PyObject* PyNumber_MatrixMultiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
を行列乗算した結果を返し、失敗するとNULL
を返す。
Pythonの式o1 @ o2
と同じ。
###<定義>
PyObject *
PyNumber_MatrixMultiply(PyObject *v, PyObject *w)
{
return binary_op(v, w, NB_SLOT(nb_matrix_multiply), "@");
}
(定義出典)
###<使用例>
case TARGET(BINARY_MATRIX_MULTIPLY): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_MatrixMultiply(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_FloorDivide(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
で除算した切捨て値を返し、失敗するとNULL
を返す。
"旧仕様の" 整数間での除算と同じ。
###<定義>
PyObject *
PyNumber_FloorDivide(PyObject *v, PyObject *w)
{
return binary_op(v, w, NB_SLOT(nb_floor_divide), "//");
}
(定義出典)
###<使用例>
case TARGET(BINARY_FLOOR_DIVIDE): {
PyObject *divisor = POP();
PyObject *dividend = TOP();
PyObject *quotient = PyNumber_FloorDivide(dividend, divisor);
Py_DECREF(dividend);
Py_DECREF(divisor);
SET_TOP(quotient);
if (quotient == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_TrueDivide(PyObject *o1, PyObject *o2)
###<概説>
成功すると、数学的なo1
のo2
による除算値に対する妥当な近似(reasonable approximation)を返し、失敗するとNULL
を返す。
全ての実数を2
を基数として表現するのは不可能なため、二進の浮動小数点数は "近似値" しか表現できず、戻り値も近似になる。
この関数に二つの整数を渡した際、浮動小数点の値を返すことがある。
###<定義>
PyObject *
PyNumber_TrueDivide(PyObject *v, PyObject *w)
{
return binary_op(v, w, NB_SLOT(nb_true_divide), "/");
}
(定義出典)
###<使用例>
case TARGET(BINARY_TRUE_DIVIDE): {
PyObject *divisor = POP();
PyObject *dividend = TOP();
PyObject *quotient = PyNumber_TrueDivide(dividend, divisor);
Py_DECREF(dividend);
Py_DECREF(divisor);
SET_TOP(quotient);
if (quotient == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Remainder(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
で除算した剰余を返し、失敗するとNULL
を返す。
Pythonの式o1 % o2
と同じ。
###<定義>
PyObject *
PyNumber_Remainder(PyObject *v, PyObject *w)
{
return binary_op(v, w, NB_SLOT(nb_remainder), "%");
}
(定義出典)
###<使用例>
case TARGET(BINARY_MODULO): {
PyObject *divisor = POP();
PyObject *dividend = TOP();
PyObject *res;
if (PyUnicode_CheckExact(dividend) && (
!PyUnicode_Check(divisor) || PyUnicode_CheckExact(divisor))) {
// fast path; string formatting, but not if the RHS is a str subclass
// (see issue28598)
res = PyUnicode_Format(dividend, divisor);
} else {
res = PyNumber_Remainder(dividend, divisor);
}
Py_DECREF(divisor);
Py_DECREF(dividend);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Divmod(PyObject *o1, PyObject *o2)
###<概説>
組み込み関数divmod()
を参照。失敗するとNULL
を返す。
Pythonの式divmod(o1, o2)
と同じ。
###<定義>
BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")
(定義出典)
###<使用例>
PyObject *result = PyNumber_Divmod(a, b);
(使用例出典)
##PyObject* PyNumber_Power(PyObject *o1, PyObject *o2, PyObject *o3)
###<概説>
組み込み関数pow()
を参照。失敗するとNULL
を返す。
Python の式pow(o1, o2, o3)
と同じ。o3
はオプションo3
を無視させたいなら、Py_None
を入れる
###<定義>
PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}
(定義出典)
###<使用例>
case TARGET(BINARY_POWER): {
PyObject *exp = POP();
PyObject *base = TOP();
PyObject *res = PyNumber_Power(base, exp, Py_None);
Py_DECREF(base);
Py_DECREF(exp);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Negative(PyObject *o)
###<概説>
成功するとo
の符号反転を返し、失敗するとNULL
を返す。Pythonの式-o
と同じ。
###<定義>
PyObject *
PyNumber_Negative(PyObject *o)
{
if (o == NULL) {
return null_error();
}
PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
if (m && m->nb_negative) {
PyObject *res = (*m->nb_negative)(o);
assert(_Py_CheckSlotResult(o, "__neg__", res != NULL));
return res;
}
return type_error("bad operand type for unary -: '%.200s'", o);
}
(定義出典)
###<使用例>
case TARGET(UNARY_NEGATIVE): {
PyObject *value = TOP();
PyObject *res = PyNumber_Negative(value);
Py_DECREF(value);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Positive(PyObject *o)
###<概説>
成功するとo
を返し、失敗するとNULL
を返す。Pythonの式+o
と同じ。
###<定義>
PyObject *
PyNumber_Positive(PyObject *o)
{
if (o == NULL) {
return null_error();
}
PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
if (m && m->nb_positive) {
PyObject *res = (*m->nb_positive)(o);
assert(_Py_CheckSlotResult(o, "__pos__", res != NULL));
return res;
}
return type_error("bad operand type for unary +: '%.200s'", o);
}
(定義出典)
###<使用例>
case TARGET(UNARY_POSITIVE): {
PyObject *value = TOP();
PyObject *res = PyNumber_Positive(value);
Py_DECREF(value);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Absolute(PyObject *o)
###<概説>
成功するとo
の絶対値を返し、失敗するとNULL
を返す。
Pythonの式abs(o)
と同じ。
###<定義>
PyObject *
PyNumber_Absolute(PyObject *o)
{
if (o == NULL) {
return null_error();
}
PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
if (m && m->nb_absolute) {
PyObject *res = m->nb_absolute(o);
assert(_Py_CheckSlotResult(o, "__abs__", res != NULL));
return res;
}
return type_error("bad operand type for abs(): '%.200s'", o);
}
(定義出典)
###<使用例>
ab = PyNumber_Absolute(m);
(使用例出典)
##PyObject* PyNumber_Invert(PyObject *o)
###<概説>
成功するとo
のビット単位反転(bitwise negation)を返し、失敗するとNULL
を返す。
Pythonの式~o
と同じ。
###<定義>
PyObject *
PyNumber_Invert(PyObject *o)
{
if (o == NULL) {
return null_error();
}
PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
if (m && m->nb_invert) {
PyObject *res = (*m->nb_invert)(o);
assert(_Py_CheckSlotResult(o, "__invert__", res != NULL));
return res;
}
return type_error("bad operand type for unary ~: '%.200s'", o);
}
(定義出典)
###<使用例>
case TARGET(UNARY_INVERT): {
PyObject *value = TOP();
PyObject *res = PyNumber_Invert(value);
Py_DECREF(value);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Lshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
だけ左シフトした結果を返し、失敗するとNULL
を返す。
Pythonの式o1 << o2
と同じ。
###<定義>
BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<")
(定義出典)
###<使用例>
case TARGET(BINARY_LSHIFT): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_Lshift(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Rshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
だけ右シフトした結果を返し、失敗するとNULL
を返す。
Pythonの式o1 >> o2
と同じ。
###<定義>
BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")
(定義出典)
###<使用例>
case TARGET(BINARY_RSHIFT): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_Rshift(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_And(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
の "ビット単位論理積 (bitwise and)" を返し、失敗するとNULL
を返す。
Pythonの式o1 & o2
と同じ。
###<定義>
BINARY_FUNC(PyNumber_And, nb_and, "&")
(定義出典)
###<使用例>
case TARGET(BINARY_AND): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_And(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Xor(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
の "ビット単位排他的論理和(bitwise exclusive or)"を返し、失敗するとNULL
を返す。
Pythonの式o1 ^ o2
と同じ。
###<定義>
BINARY_FUNC(PyNumber_Xor, nb_xor, "^")
(定義出典)
###<使用例>
case TARGET(BINARY_XOR): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_Xor(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Or(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
の"ビット単位論理和 (bitwise or)"を返し失敗するとNULL
を返す。
Pythonの式o1 | o2
と同じ。
###<定義>
BINARY_FUNC(PyNumber_Or, nb_or, "|")
(定義出典)
###<使用例>
case TARGET(BINARY_OR): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_Or(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceAdd(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
を加算した結果を返し、失敗するとNULL
を返す。o1
がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 += o2
と同じ。
###<定義>
PyObject *
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
{
PyObject *result = BINARY_IOP1(v, w, NB_SLOT(nb_inplace_add),
NB_SLOT(nb_add), "+=");
if (result == Py_NotImplemented) {
PySequenceMethods *m = Py_TYPE(v)->tp_as_sequence;
Py_DECREF(result);
if (m != NULL) {
binaryfunc func = m->sq_inplace_concat;
if (func == NULL)
func = m->sq_concat;
if (func != NULL) {
result = func(v, w);
assert(_Py_CheckSlotResult(v, "+=", result != NULL));
return result;
}
}
result = binop_type_error(v, w, "+=");
}
return result;
}
(定義出典)
###<使用例>
case TARGET(INPLACE_ADD): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *sum;
if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) {
sum = unicode_concatenate(tstate, left, right, f, next_instr);
/* unicode_concatenate consumed the ref to left */
}
else {
sum = PyNumber_InPlaceAdd(left, right);
Py_DECREF(left);
}
Py_DECREF(right);
SET_TOP(sum);
if (sum == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceSubtract(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
からo2
を減算した結果を返し、失敗するとNULL
を返す。o1
が in-place 演算をサポートする場合、in-place 演算を行う。
Pythonの文o1 -= o2
と同じ。
###<定義>
INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=")
(定義出典)
###<定義補足>
#define INPLACE_BINOP(func, iop, op, op_name) \
PyObject * \
func(PyObject *v, PyObject *w) { \
return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \
}
static PyObject *
binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot
)
{
PyNumberMethods *mv = Py_TYPE(v)->tp_as_number;
if (mv != NULL) {
binaryfunc slot = NB_BINOP(mv, iop_slot);
if (slot) {
PyObject *x = (slot)(v, w);
assert(_Py_CheckSlotResult(v, op_name, x != NULL));
if (x != Py_NotImplemented) {
return x;
}
Py_DECREF(x);
}
}
return binary_op1(v, w, op_slot);
}
大筋を変えない程度に改変。
###<使用例>
case TARGET(INPLACE_SUBTRACT): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *diff = PyNumber_InPlaceSubtract(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(diff);
if (diff == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceMultiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
を乗算した結果を返し、失敗するとNULL
を返す。o1がin-place演算をサポートする場合、in-place演算を行う。 Pythonの文
o1 *= o2`と同じ。
###<定義>
PyObject *
PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)
{
PyObject *result = BINARY_IOP1(v, w, NB_SLOT(nb_inplace_multiply),
NB_SLOT(nb_multiply), "*=");
if (result == Py_NotImplemented) {
ssizeargfunc f = NULL;
PySequenceMethods *mv = Py_TYPE(v)->tp_as_sequence;
PySequenceMethods *mw = Py_TYPE(w)->tp_as_sequence;
Py_DECREF(result);
if (mv != NULL) {
f = mv->sq_inplace_repeat;
if (f == NULL)
f = mv->sq_repeat;
if (f != NULL)
return sequence_repeat(f, v, w);
}
else if (mw != NULL) {
/* Note that the right hand operand should not be
* mutated in this case so sq_inplace_repeat is not
* used. */
if (mw->sq_repeat)
return sequence_repeat(mw->sq_repeat, w, v);
}
result = binop_type_error(v, w, "*=");
}
return result;
}
(定義出典)
###<使用例>
case TARGET(INPLACE_MULTIPLY): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceMultiply(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceMatrixMultiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
を行列乗算した結果を返し、失敗するとNULL
を返す。o1
がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 @= o2
と同じ。
###<定義>
PyObject *
PyNumber_InPlaceMatrixMultiply(PyObject *v, PyObject *w)
{
return binary_iop(v, w, NB_SLOT(nb_inplace_matrix_multiply),
NB_SLOT(nb_matrix_multiply), "@=");
}
(定義出典)
###<使用例>
case TARGET(INPLACE_MATRIX_MULTIPLY): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceFloorDivide(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
で除算した切捨て値を返し、失敗するとNULL
を返す。o1
がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 //= o2
と同じ。
###<定義>
PyObject *
PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w)
{
return binary_iop(v, w, NB_SLOT(nb_inplace_floor_divide),
NB_SLOT(nb_floor_divide), "//=");
}
(定義出典)
###<使用例>
case TARGET(INPLACE_FLOOR_DIVIDE): {
PyObject *divisor = POP();
PyObject *dividend = TOP();
PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor);
Py_DECREF(dividend);
Py_DECREF(divisor);
SET_TOP(quotient);
if (quotient == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceTrueDivide(PyObject *o1, PyObject *o2)
###<概説>
成功すると、数学的なo1
のo2
による除算値に対する妥当な近似 (reasonable approximation) を返し、失敗するとNULL
を返す。
全ての実数を2
を基数として表現するのは不可能なため、二進の浮動小数点数は "近似値" しか表現できまず、戻り値も近似になる。
この関数に二つの整数を渡した際、浮動小数点の値を返すことがある。o1
が in-place 演算をサポートする場合、in-place 演算を行う。
###<定義>
PyObject *
PyNumber_InPlaceTrueDivide(PyObject *v, PyObject *w)
{
return binary_iop(v, w, NB_SLOT(nb_inplace_true_divide),
NB_SLOT(nb_true_divide), "/=");
}
(定義出典)
###<使用例>
case TARGET(INPLACE_TRUE_DIVIDE): {
PyObject *divisor = POP();
PyObject *dividend = TOP();
PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor);
Py_DECREF(dividend);
Py_DECREF(divisor);
SET_TOP(quotient);
if (quotient == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceRemainder(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
で除算した剰余を返し、,失敗するとNULL
を返す。o1
が in-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 %= o2
と同じ。
###<定義>
PyObject *
PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
{
return binary_iop(v, w, NB_SLOT(nb_inplace_remainder),
NB_SLOT(nb_remainder), "%=");
}
(定義出典)
###<使用例>
case TARGET(INPLACE_MODULO): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *mod = PyNumber_InPlaceRemainder(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(mod);
if (mod == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlacePower(PyObject *o1, PyObject *o2, PyObject *o3)
###<概説>
組み込み関数pow()
を参照してください。失敗するとNULL
を返す。o1
が in-place 演算をサポートする場合、in-place 演算を行う。この関数はo3
がPy_None
の場合は Python 文o1 **= o2
と同じで、それ以外の場合はpow(o1, o2, o3)
の in-place 版です。o3
を無視させたいなら、Py_None
を入れる。
###<定義>
PyObject *
PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
{
return ternary_iop(v, w, z, NB_SLOT(nb_inplace_power),
NB_SLOT(nb_power), "**=");
}
(定義出典)
###<使用例>
case TARGET(INPLACE_POWER): {
PyObject *exp = POP();
PyObject *base = TOP();
PyObject *res = PyNumber_InPlacePower(base, exp, Py_None);
Py_DECREF(base);
Py_DECREF(exp);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceLshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
だけ左シフトした結果を返し、失敗するとNULL
を返す。o1
がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 <<= o2
と同じ。
###<定義>
INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=")
(定義出典)
###<使用例>
case TARGET(INPLACE_LSHIFT): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceLshift(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceRshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
をo2
だけ右シフトした結果を返し、失敗するとNULL
を返す。o1
が in-place 演算をサポートする場合、in-place 演算を行う。
Python の文o1 >>= o2
と同じ。
###<定義>
INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=")
(定義出典)
###<使用例>
case TARGET(INPLACE_RSHIFT): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceRshift(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceAnd(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
の "ビット単位論理積 (bitwise and)" を返し、失敗するとNULL
を返す。o1
が in-place 演算をサポートする場合、in-place 演算を行う。
Pythonの文o1 &= o2
と同じ。
###<定義>
INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=")
(定義出典)
###<使用例>
case TARGET(INPLACE_AND): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceAnd(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceXor(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
の "ビット単位排他的論理和 (bitwise exclusive or)" を返し、失敗するとNULL
を返す。o1
が in-place 演算をサポートする場合、in-place 演算を行う。
Python の文o1 ^= o2
と同じ。
###<定義>
INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=")
(定義出典)
###<使用例>
case TARGET(INPLACE_XOR): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceXor(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_InPlaceOr(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1
とo2
の "ビット単位論理和 (bitwise or)" を返し失敗するとNULL
を返す。o1
が in-place 演算をサポートする場合、in-place 演算を行う。
Python の文o1 |= o2
と同じ。
###<定義>
INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=")
(定義出典)
###<使用例>
case TARGET(INPLACE_OR): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_InPlaceOr(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}
(使用例出典)
##PyObject* PyNumber_Long(PyObject *o)
###<概説>
成功するとo
を整数に変換したものを返し、失敗するとNULL
を返す。
Pythonの式int(o)
と同じ。
###<定義>
PyObject *
PyNumber_Long(PyObject *o)
{
...
m = Py_TYPE(o)->tp_as_number;
if (m && m->nb_int) { /* This should include subclasses of int */
/* Convert using the nb_int slot, which should return something
of exact type int. */
result = m->nb_int(o);
...
if (!result || PyLong_CheckExact(result)) {
return result;
}
...
(定義出典)
###<使用例>
iobj = PyNumber_Long(v);
(使用例出典)
##PyObject* PyNumber_Float(PyObject *o)
###<概説>
成功するとo
を浮動小数点数に変換したものを返し、失敗するとNULL
を返す。
Pythonの式float(o)
と同じ。
###<定義>
PyObject *
PyNumber_Float(PyObject *o)
{
...
PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
if (m && m->nb_float) { /* This should include subclasses of float */
PyObject *res = m->nb_float(o);
...
if (!res || PyFloat_CheckExact(res)) {
return res;
}
...
(定義出典)
###<使用例>
tmp = PyNumber_Float(i);
(使用例出典)
##PyObject* PyNumber_Index(PyObject *o)
###<概説>
o
をPythonのint型に変換し、成功したらその値を返す。失敗したらNULL
が返され、TypeError
例外が送出される。
###<定義>
PyObject *
PyNumber_Index(PyObject *item)
{
PyObject *result = _PyNumber_Index(item);
if (result != NULL && !PyLong_CheckExact(result)) {
Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
}
return result;
}
(定義出典)
/* Return a Python int from the object item.
Can return an instance of int subclass.
Raise TypeError if the result is not an int
or if the object cannot be interpreted as an index.
*/
PyObject *
_PyNumber_Index(PyObject *item)
{
...
PyObject *result = Py_TYPE(item)->tp_as_number->nb_index(item);
...
if (!result || PyLong_CheckExact(result)) {
return result;
}
...
(補足出典)
###<使用例>
step = PyNumber_Index(step);
(使用例出典)
##PyObject* PyNumber_ToBase(PyObject *n, int base)
###<概説>
base 進数に変換された整数n
を文字列として返す。 base 引数は2, 8, 10または16のいずれかでなければならない。 基数2、8、16について、返される文字列の先頭には基数マーカー '0b' 、 '0o' または '0x' が、それぞれ付与される。 もしn
が Python のint型でなければ、まずPyNumber_Index()
で変換される。
###<定義>
PyObject *
PyNumber_ToBase(PyObject *n, int base)
{
if (!(base == 2 || base == 8 || base == 10 || base == 16)) {
PyErr_SetString(PyExc_SystemError,
"PyNumber_ToBase: base must be 2, 8, 10 or 16");
return NULL;
}
PyObject *index = _PyNumber_Index(n);
if (!index)
return NULL;
PyObject *res = _PyLong_Format(index, base);
Py_DECREF(index);
return res;
}
(定義出典)
###<使用例>
static PyObject *
builtin_bin(PyObject *module, PyObject *number)
/*[clinic end generated code: output=b6fc4ad5e649f4f7 input=53f8a0264bacaf90]*/
{
return PyNumber_ToBase(number, 2);
}
(使用例出典)
##Py_ssize_t PyNumber_AsSsize_t(PyObject *o, PyObject *exc)
###<概説>
o
を整数として解釈可能だった場合、Py_ssize_t型の値に変換して返す。呼び出しが失敗したら、例外が送出され、-1
が返される。
もしo
がPythonのintに変換できたのに、Py_ssize_tへの変換がOverflowError
になる場合は、exc
引数で渡された型 (普通はIndexError
かOverflowError
) の例外を送出します。もし、exc
がNULL
なら、例外はクリアされて、値が負の場合はPY_SSIZE_T_MIN
へ、正の場合はPY_SSIZE_T_MAX
へと制限される。
###<定義>
Py_ssize_t
PyNumber_AsSsize_t(PyObject *item, PyObject *err)
{
...
/* We're done if PyLong_AsSsize_t() returns without error. */
result = PyLong_AsSsize_t(value);
...
return result;
}
(定義出典)
###<使用例>
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
(使用例出典)
##int PyIndex_Check(PyObject *o)
###<概説>
o
がインデックス整数である場合 (tp_as_number構造体のnb_indexスロットが埋まっている場合) に1
を返し、そうでない場合に0
を返す。 この関数は常に成功する。
###<定義>
int
PyIndex_Check(PyObject *obj)
{
return _PyIndex_Check(obj);
}
(定義出典)
###<定義補足>
// Fast inlined version of PyIndex_Check()
static inline int
_PyIndex_Check(PyObject *obj)
{
PyNumberMethods *tp_as_number = Py_TYPE(obj)->tp_as_number;
return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
}
(定義補足出典)
###<使用例>
if (PyIndex_Check(item)) {
(使用例出典)
##蛇足
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
{
...
int opcode; /* Current opcode */
int oparg; /* Current opcode argument, if any */
...
/* push frame */
tstate->frame = f;
co = f->f_code;
...
names = co->co_names;
consts = co->co_consts;
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + co->co_nlocals;
...
stack_pointer = f->f_valuestack + f->f_stackdepth;
...
main_loop:
for (;;) {
...
opcode = _Py_OPCODE(*next_instr);
...
switch (opcode) {
/* BEWARE!
It is essential that any operation that fails must goto error
and that all operation that succeed call [FAST_]DISPATCH() ! */
case TARGET(NOP): {
DISPATCH();
}
case TARGET(LOAD_FAST): {
...
#参考にさせていただいた本・ページ
#感想
バージョンが混ざってしまっているが、雰囲気を掴みたかっただけなので、そこは厳密にはしなかった。
使用例については、CPythonの中で用いられているものに限定した。