假设我们写了一个小类:

class K:
    pass
obj = K()


是下面的代码...

total = 4 + obj


...与以下内容基本相同?

import io
try:
    total = 4.__add__(obj)
except NotImplementedError:
    try:
        total = obj.__radd__(4)
    except AttributeError:
        # type(obj) does not have an `__radd__` method
        with io.StringIO() as string_stream:
            print(
                "unsupported operand type(s) for +:",
                repr(type(4).__name__),
                "and",
                repr(type(obj).__name__),
                file=string_stream
            ) # `repr` puts quotes around the type names
            msg = string_stream.getvalue()
        raise TypeError(msg) from None

最佳答案

实际上,触发__radd__()的行为不是NotImplementedError,而是称为NotImplemented的特殊对象:

>>> help(NotImplemented)
Help on NotImplementedType object:

class NotImplementedType(object)
 |  Methods defined here:
 |
 |  __reduce__(...)
 |      Helper for pickle.
 |
 |  __repr__(self, /)
 |      Return repr(self).
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.


NotImplementedError仍将作为错误传播。但是,返回NotImplemented对象(而不是引发错误)将允许__radd__()触发:

>>> class A:
...     def __add__(self, other):
...         raise NotImplementedError()
...
>>> class B:
...     def __add__(self, other):
...         print("__add__ was called")
...     def __radd__(self, other):
...         print("__radd__ was called")
...
>>> class C:
...     def __add__(self, other):
...         return NotImplemented
...
>>> a, b, c = A(), B(), C()
>>> b + a
__add__ was called
>>> a + b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __add__
NotImplementedError
>>> b + c
__add__ was called
>>> c + b
__radd__ was called

08-24 21:21