Why Return Notimplemented Instead of Raising Notimplementederror

Why return NotImplemented instead of raising NotImplementedError

It's because __lt__() and related comparison methods are quite commonly used indirectly in list sorts and such. Sometimes the algorithm will choose to try another way or pick a default winner. Raising an exception would break out of the sort unless caught, whereas NotImplemented doesn't get raised and can be used in further tests.

http://jcalderone.livejournal.com/32837.html

To summarise that link:

"NotImplemented signals to the runtime that it should ask someone else to satisfy the operation. In the expression a == b, if a.__eq__(b) returns NotImplemented, then Python tries b.__eq__(a). If b knows enough to return True or False, then the expression can succeed. If it doesn't, then the runtime will fall back to the built-in behavior (which is based on identity for == and !=)."

Why doesn't NotImplemented raise a TypeError?

When you return NotImplemented you indicate that you do not know if __ne__ should return True or False.

Normally, Python will then swap the operands; if a != b results in NotImplemented, it'll try b != a instead. That'll fail here too, since you use the same type on both sides of the operator. For the != operator, Python will then fall back to comparing their memory addresses, and these are not the same (two separate instances), so False is returned.

See the do_richcompare C function for details.

You'll have to raise TypeError() manually if that is your expected outcome.

Why is int raising a TypeError instead of NotImplemented?

Your understanding of the numeric model is correct:

>>> class Foob(object):
... def __add__(self, o): return 1
... def __radd__(self, o): return 2
...
>>> f = Foob()
>>> f + f
1
>>> f + 5
1
>>> 5 + f
2

Your __radd__ code must eventually be raising a TypeError - possibly by calling int's + with an incorrect type. What's the stack trace look like?

is `__radd__` called if `__add__` raises `NotImplementedError`?

The behavior that triggers __radd__() is not, in fact, a NotImplementedError, but rather a special object called 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 NotImplementedError will still propagate as an error. However, returning the NotImplemented object (rather than raising an error) will allow __radd__() to trigger:

>>> 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

raise NotImplementedError NotImplementedError

Python 3.8 made a backwards-incompatible change to the asyncio package used by Tornado. Applications that use Tornado on Windows with Python 3.8 must call asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) at the beginning of their main file/function. (as documented on the home page of tornadoweb.org)



Related Topics



Leave a reply



Submit