调用+;=`关于C++; 我在C++中编写了一个Python模块。

调用+;=`关于C++; 我在C++中编写了一个Python模块。,python,c++,python-3.x,python-extensions,Python,C++,Python 3.x,Python Extensions,在某一点上,我需要向另一个对象添加任意类型的PyObject。换句话说,执行与Python中的a+=b相同的操作。但是我还没有在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

在某一点上,我需要向另一个对象添加任意类型的
PyObject
。换句话说,执行与Python中的
a+=b
相同的操作。但是我还没有在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));
}
如果如建议的那样,
\uuuuu iadd\uuuuu
不可用,则返回到
\uuuu添加

在某一点上,我需要将任意类型的PyObject添加到另一个PyObject。换句话说,执行与Python中a+=b相同的操作。但是我还没有在API中找到一个函数来实现这一点

你找不到的函数是

x+=y
在Python级别上相当于

sum=PyNumber\u inpeacedd(x,y);
Py_DECREF(x);
x=总和;
在C级。(如果需要,还可以同时保留
sum
x
,这对于异常处理非常有用。)


PyNumber\u inpeaceadd
处理
+=
的完整调度逻辑,包括
\u iadd\u
、双方的
\u add\u
方法(按正确顺序)、未实现的
哨兵和
nb\u inplace\u add
、nb\u add
、sq inplace\u concat>,和
sq_concat
C级钩子。

“发现Python float、int和str都没有实现这些方法”:因为这些类型是不可变的。不能递增/更改它们,“+=”运算符是“假”运算符
a+=1
a=a+1
是一样的(反汇编显示
in place\u ADD
,但那不是真正的in place,而且
\u iadd\u
不存在)如果对象不提供
\uuuu iadd\uuuu
,您可以退回到加法,然后返回结果
操作符
模块有一个
\uu iadd\uuuu
函数,该函数应该做正确的事情。就这么说吧,我明白了。在C++中,如在代码< >代码> PyFoAtObjult<代码>中,是否会有任何损害,例如:代码> A->ObjFVAL=4.2;<代码>?在
iadd
案例中,您仍然需要重新分配到
a
。“就地”方法返回不同的对象是可能的,尽管不常见。我做了与您建议相反的事情,原因与您的完全相同。对于我的应用程序,如果
iadd
返回了一个不同的对象,我希望我的原始对象(假定是递增的)而不是返回的对象。您还缺少对右侧方法的分派,以及先尝试哪一方的
nbu add
的逻辑。“如果
iadd
返回了一个不同的对象,我想要的是我原来的,应该是递增的对象,而不是返回的对象”-这有点奇怪,而不是Python的
+=
的工作方式。”这有点奇怪“:这是历史编程代码的一部分。如果
iadd
返回一个哨兵信号,指示添加是否成功,如果两种类型不兼容,则添加可能失败,我将丢失bin对象。