繁体   English   中英

在 C++ 中的 PyObject 上调用 `+=`

[英]Call `+=` on a PyObject in C++

我正在 C++ 中编写 Python 模块。

在某个时刻,我需要将任意类型的PyObject添加到另一个中。 换句话说,执行与 Python 中a += b相同的操作。 但是我无法在 API 中找到可以做到这一点的 function。

我尝试执行以下操作,

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 floatintstr都没有实现这些方法。

API 中是否有应用通用+=的 function ? 如果没有,我怎么写?

在某个时刻,我需要将任意类型的 PyObject 添加到另一个中。 换句话说,执行与 Python 中的 a += b 相同的操作。 但是我无法在 API 中找到可以做到这一点的 function。

您找不到的 function 是PyNumber_InPlaceAdd

x += y

在 Python 级别相当于

sum = PyNumber_InPlaceAdd(x, y);
Py_DECREF(x);
x = sum;

在 C 级别。 (如果需要,您也可以同时保留sumx ,这对于异常处理很有用。)

PyNumber_InPlaceAdd处理+=的完整调度逻辑,包括__iadd__ 、双方的__add__方法(按正确顺序)、 NotImplemented sentinel 以及nb_inplace_addnb_addsq_inplace_concatsq_concat C 级挂钩。

我最终做了这样的事情:

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));
}

正如Jean-François Fabre所建议的那样,如果__iadd__不可用,那将依赖__add__

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM