调用+;=`关于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对象。