代码之家  ›  专栏  ›  技术社区  ›  Samuel Muldoon

如果“\uuuu add\uuuuuu”引发“NotImplementedError”,是否调用“\uuuu radd”?

  •  0
  • Samuel Muldoon  · 技术社区  · 6 年前

    假设我们写一个小类:

    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
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   Green Cloak Guy    6 年前

    触发的行为 __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.
    

    A. 未实现错误 仍将作为错误传播。然而,返回 未实施 对象(而不是引发错误)将允许 __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