从python中,我们可以像这样重载运算符:
class X:
def __add__(self, i):
return i+3;
def __radd__(self, i):
return i+4
x = X()
print x+0 # prints 3
print 0+x # prints 4
如果我们希望在C扩展模块中实现X,我们必须显式注册运算符重载。 __add__是可行的:
X_type.tp_as_number.nb_add = &X_add;
但是__radd__似乎没有相应的插槽。它在哪里?
答案 0 :(得分:1)
Python使用两种不同的方法来处理正常和反向二进制操作。所有版本的Python 2.x都支持“旧样式”方法,并且最新版本支持“新风格”方法(从2.3开始)。 Python 3.x仅支持“新样式”数字类型。
“旧样式”数字类型预期的操作数已经转换为通用类型。 nb_coerce插槽指向将其他数字类型转换为自定义类型的函数。
“新样式”数字类型不使用nb_coerce,但应检查其他操作数的类型。使用Python 2.x,您需要在tp_flags插槽中包含Py_TPFLAGS_CHECKTYPES。 Python 3没有什么特别需要做的。
摘录来自Python 2.7 abstract.c文件:
/*
Calling scheme used for binary operations:
v w Action
-------------------------------------------------------------------
new new w.op(v,w)[*], v.op(v,w), w.op(v,w)
new old v.op(v,w), coerce(v,w), v.op(v,w)
old new w.op(v,w), coerce(v,w), v.op(v,w)
old old coerce(v,w), v.op(v,w)
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
v->ob_type
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
*/
由于Python 3.x仅支持“新样式”数字类型,因此仅使用第一个调用方案。由于“新风格”可以与Python 2.7一起使用,我通常使用新风格。