def _binary_operator_error(t1, t2, name): raise TypeError("unsupported operand type(s) for %s: '%s' and '%s'" % (t1, t2, name)) def binary_operator(name, rname, op1, op2): t1 = type(op1) t2 = type(op2) if issubclass(t2, t1): if rname in t2.__dict__: result = t2.__dict__[rname](op2, op1) if result is not NotImplemented: return result if name in t1.__dict__: result = t1.__dict__[name](op1, op2) if result is not NotImplemented: return result else: if name in t1.__dict__: result = t1.__dict__[name](op1, op2) if result is not NotImplemented: return result if rname in t2.__dict__: result = t2.__dict__[rname](op2, op1) if result is not NotImplemented: return result _binary_operator_error(t1, t2, name) # In CPython this fails for 2.5, 2.6, 3.1 (and Unladen Swallow) # PyPy and Jython both succeed assert binary_operator('__add__', '__radd__', 3.0, 4j) == 3.0 + 4j # I believe the problem is in the function wrap_binaryfunc_r # in typeobject.c # wrap_binaryfunc_r returns NotImplemented for op(a, b) # if b is not subtype of a, but it should let the slot # function handle subtyping.