Dan*_*use 6 python string operator-overloading
我想这样做:
x %doSomething% y
Run Code Online (Sandbox Code Playgroud)
对于任何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
Run Code Online (Sandbox Code Playgroud)
注意:我提交了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);
Run Code Online (Sandbox Code Playgroud)
(从Python 3.5源代码中,PyUnicodePython str类型在哪里).
这很不幸,因为对于其他所有类型,您可以LHS.__mod__通过使用右侧操作数的子类来阻止调用该方法; 从文件:
注意:如果右操作数的类型是左操作数类型的子类,并且该子类提供了操作的反射方法,则此方法将在左操作数的非反射方法之前调用.此行为允许子类覆盖其祖先的操作.
这将是唯一的选择,str % other永远不会返回NotImplemented,所有 RHS类型都被接受(实际str.__mod__方法只接受strRHS的对象,但在这种情况下不调用).
我认为这是Python中的一个错误,存在问题#28598.