0

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

4

1 回答 1

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

于 2012-08-20T04:54:56.707 回答