我想这样做:
- x %doSomething% y
对于任何x和任何y都很容易做到(见下面的代码),除非x是str.
是否有任何方法(例如添加特殊方法或引发特定错误)导致旧样式字符串格式化失败(类似于1%doSomthing如何通过TypeError失败)并恢复到doSomething对象中定义的__rmod__方法?
- class BinaryMessage(object):
- def __init__(self,fn):
- self._fn = fn
- def __rmod__(self,LHS):
- return BinaryMessagePartial(self._fn,LHS)
- class BinaryMessagePartial(object):
- def __init__(self,fn,LHS):
- self._fn = fn
- self._LHS = LHS
- def __mod__(self,RHS):
- return self._fn(self._LHS,RHS)
- def _doSomething(a,b):
- return a + b
- doSomething = BinaryMessage(_doSomething)
- result = 5 %doSomething% 6
- assert result == 11
解决方法
注意:我提交了Python 2.7和3.5及更高版本的补丁.这些已经登陆并且是2.7.14,3.5.4,3.6.1和3.7的一部分,其中OP示例现在按预期工作.对于旧版本,请参阅下文.
不幸的是,这在Python中目前是不可能的.行为在评估循环中是硬编码的:
- TARGET(BINARY_MODULO) {
- PyObject *divisor = POP();
- PyObject *dividend = TOP();
- PyObject *res = PyUnicode_CheckExact(dividend) ?
- PyUnicode_Format(dividend,divisor) :
- PyNumber_Remainder(dividend,divisor);
(从Python 3.5 source code开始,PyUnicode是Python str类型).
这是不幸的,因为对于其他所有类型,您可以通过使用右侧操作数的子类来阻止LHS .__ mod__方法;从documentation:
Note: If the right operand’s type is a subclass of the left operand’s type and that subclass provides the reflected method for the operation,this method will be called before the left operand’s non-reflected method. This behavior allows subclasses to override their ancestors’ operations.
这将是唯一的选项,str%other永远不会返回NotImplemented,所有RHS类型都被接受(实际的str.__mod__
method只接受RHS的str对象,但在这种情况下不调用).
我认为这是Python中的一个错误,提交为issue #28598.