Python:如何从C重载反射的数字运算符

时间:2012-08-19 19:08:22

标签: python python-2.7

从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__似乎没有相应的插槽。它在哪里?

1 个答案:

答案 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一起使用,我通常使用新风格。