在 C++ 中的 PyObject 上调用 `+=`
Call `+=` on a PyObject in C++
我正在用 C++ 编写 Python 模块。
在某个时候,我需要将任意类型的PyObject
添加到另一个。换句话说,就像 a += b
在 Python 中做的一样。但是我没能在 API 中找到一个函数可以做到这一点。
我尝试执行以下操作,
PyObject* increment(PyObject* a, PyObject* b) {
const auto tp = Py_TYPE(a);
[&]{
if (const auto nb = tp->tp_as_number)
if (auto iadd = nb->nb_inplace_add)
return iadd;
if (const auto sq = tp->tp_as_sequence)
if (auto iadd = sq->sq_inplace_concat)
return iadd;
throw error(PyExc_TypeError,
"type "s+(tp->tp_name)+" does not provide __iadd__");
}()(a,b);
return a;
}
但发现 Python float
、int
和 str
都没有实现这些方法。
API 中是否有应用通用 +=
的函数?如果没有,我怎么写?
我最终做了这样的事情:
static PyObject* increment(PyObject*& a, PyObject* b) {
const auto tp = Py_TYPE(a);
if (const auto nb = tp->tp_as_number) {
if (auto iadd = nb->nb_inplace_add)
return iadd(a,args), a;
if (auto add = nb->nb_add)
return a = add(a,b);
}
if (const auto sq = tp->tp_as_sequence) {
if (auto iadd = sq->sq_inplace_concat)
return iadd(a,b), a;
if (auto add = sq->sq_concat)
return a = add(a,b);
}
throw error(PyExc_TypeError,
"cannot increment "s+(tp->tp_name)+" by "+(Py_TYPE(b)->tp_name));
}
如果 __iadd__
不可用,则返回 __add__
,如 Jean-François Fabre 所建议。
At a certain point, I need to add a PyObject of an arbitrary type to another one. In other words, do the same as a += b would do in Python. But I haven't been able to find a function in the API that does that.
您找不到的函数是 PyNumber_InPlaceAdd
。
x += y
在Python级别相当于
sum = PyNumber_InPlaceAdd(x, y);
Py_DECREF(x);
x = sum;
C级。 (如果需要,您也可以同时保留 sum
和 x
,这对异常处理很有用。)
PyNumber_InPlaceAdd
处理 +=
的完整调度逻辑,包括 __iadd__
,双方的 __add__
方法(以正确的顺序), NotImplemented
哨兵,以及 nb_inplace_add
、nb_add
、sq_inplace_concat
和 sq_concat
C 级挂钩。
我正在用 C++ 编写 Python 模块。
在某个时候,我需要将任意类型的PyObject
添加到另一个。换句话说,就像 a += b
在 Python 中做的一样。但是我没能在 API 中找到一个函数可以做到这一点。
我尝试执行以下操作,
PyObject* increment(PyObject* a, PyObject* b) {
const auto tp = Py_TYPE(a);
[&]{
if (const auto nb = tp->tp_as_number)
if (auto iadd = nb->nb_inplace_add)
return iadd;
if (const auto sq = tp->tp_as_sequence)
if (auto iadd = sq->sq_inplace_concat)
return iadd;
throw error(PyExc_TypeError,
"type "s+(tp->tp_name)+" does not provide __iadd__");
}()(a,b);
return a;
}
但发现 Python float
、int
和 str
都没有实现这些方法。
API 中是否有应用通用 +=
的函数?如果没有,我怎么写?
我最终做了这样的事情:
static PyObject* increment(PyObject*& a, PyObject* b) {
const auto tp = Py_TYPE(a);
if (const auto nb = tp->tp_as_number) {
if (auto iadd = nb->nb_inplace_add)
return iadd(a,args), a;
if (auto add = nb->nb_add)
return a = add(a,b);
}
if (const auto sq = tp->tp_as_sequence) {
if (auto iadd = sq->sq_inplace_concat)
return iadd(a,b), a;
if (auto add = sq->sq_concat)
return a = add(a,b);
}
throw error(PyExc_TypeError,
"cannot increment "s+(tp->tp_name)+" by "+(Py_TYPE(b)->tp_name));
}
如果 __iadd__
不可用,则返回 __add__
,如 Jean-François Fabre 所建议。
At a certain point, I need to add a PyObject of an arbitrary type to another one. In other words, do the same as a += b would do in Python. But I haven't been able to find a function in the API that does that.
您找不到的函数是 PyNumber_InPlaceAdd
。
x += y
在Python级别相当于
sum = PyNumber_InPlaceAdd(x, y);
Py_DECREF(x);
x = sum;
C级。 (如果需要,您也可以同时保留 sum
和 x
,这对异常处理很有用。)
PyNumber_InPlaceAdd
处理 +=
的完整调度逻辑,包括 __iadd__
,双方的 __add__
方法(以正确的顺序), NotImplemented
哨兵,以及 nb_inplace_add
、nb_add
、sq_inplace_concat
和 sq_concat
C 级挂钩。