Is it possible to overwrite str's % behaviour using __rmod__?

北战南征 提交于 2019-12-23 09:27:52

问题


I'd like to do:

x %doSomething% y

which is easy enough to do (see code below) for any x and any y except in the case that x is a str.

Is there any way (e.g. adding a special method or raising a specific error) to cause old style string formatting to fail (similarly to how 1 %doSomthing fails with a TypeError) and revert to the __rmod__ method defined in the doSomething object?

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

回答1:


Note: I submitted patches for Python 2.7, and 3.5 and up. These have landed and are part of 2.7.14, 3.5.4, 3.6.1 and 3.7, where the OP example now works as expected. For older versions, see below.


Unfortunately, this is not currently possible in Python. The behaviour is hardcoded in the evaluation loop:

TARGET(BINARY_MODULO) {
    PyObject *divisor = POP();
    PyObject *dividend = TOP();
    PyObject *res = PyUnicode_CheckExact(dividend) ?
        PyUnicode_Format(dividend, divisor) :
        PyNumber_Remainder(dividend, divisor);

(From the Python 3.5 source code, where PyUnicode is the Python str type).

This is unfortunate, because for every other type you can prevent the LHS.__mod__ method to be invoked by using a subclass for the right-hand operand; from the 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.

This would have been the only option here, str % other never returns NotImplemented, all RHS types are accepted (the actual str.__mod__ method only accepts str objects for the RHS, but is not called in this case).

I consider this a bug in Python, filed as issue #28598.



来源:https://stackoverflow.com/questions/40402235/is-it-possible-to-overwrite-strs-behaviour-using-rmod

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!