Note:我提交了 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 源代码 https://hg.python.org/cpython/file/v3.5.2/Python/ceval.c#l1545, where PyUnicode
是Pythonstr
type).
这是不幸的,因为对于所有其他类型你可以防止LHS.__mod__
通过使用右侧操作数的子类来调用的方法;来自文档 https://docs.python.org/3/reference/datamodel.html#object.__ror__:
Note:如果右操作数的类型是左操作数类型的子类,并且该子类为该操作提供了反射方法,则该方法将在左操作数的非反射方法之前被调用。这种行为允许子类覆盖其祖先的操作。
这本来是这里唯一的选择,str % other
一去不复返NotImplemented
, all接受 RHS 类型(实际str.__mod__ method https://hg.python.org/cpython/file/v3.5.2/Objects/unicodeobject.c#l13670只接受str
RHS 的对象,但在本例中未调用)。
我认为这是 Python 中的一个错误,归档为问题#28598 http://bugs.python.org/issue28598.