Ethan Furman <et...@stoneleaf.us> added the comment:

Serhiy:
------
> First, it is impossible. nb_bool and PyObject_IsTrue() can return
> only three value: 1 for true, 0 for false, and -1 for error.

Huh.  How is -1 interpreted?  Does it become a TypeError?


> It is not possible to represent NotImplemented without breaking all
> extensions.
> 
> Currently
> 
>     if not a:
>         b()
>     else:
>         c()
> 
> is equivalent to
> 
>    if a:
>        c()
>     else:
>         b()
> 
> If a is NotImplemented, what branch be executed in every case?

Side-stepping to other __dunder__ methods for a moment: if, for example, both 
__add__ and __radd__ return NotImplemented then the interpreter will convert 
that into a TypeError.

So my thinking is that when the interpreter gets the `NotImplemented` returned 
by either `if a` or by `if not a` that it would be converted to a `TypeError`, 
meaning none of the branches would be executed as an exception would be raised 
instead.

> Second, it would not help. Because real-world examples are not always so
> trivial as "return not self.__lt__(other)". It may be a part of more
> complex expression, e.g.:
> 
>     return super().__eq__(other) and self.attr == other.attr

I don't see the problem -- breaking it down:

    return super().__eq__(other) and self.attr == other.attr

becomes

    return NotImplemented and ...

and the `and` machinery sees it has a `NotImplemented` and raises a 
`TypeError`.  The same would be true if the `__eq__` operation returned 
`NotImplemented`.

So to make that work, `and` and `or` would have to check if one of the operands 
is `NotImplemented`.  Are there others that would need to have that check?

The reason I would prefer this solution is that if it could behave as I 
described above, the `TypeError` would point at the user's line of code as 
being the problem, and not inside the __dunder__:

    class NoAdd:
        #
        def __add__(self, other):
            return NotImplemented
        #
        def __radd__(self, other):
            # fake a NotImplemented TypeError from bool(NotImplemented)
            raise TypeError("cannot boolean NotImplemented")

    # what we should see, since the error is in the users' code
    --> NoAdd() + 7
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'NoAdd' and 'int'

    # what we will see -- a leaky implementation detail
    --> 7 + NoAdd()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in __radd__
    TypeError: cannot boolean NotImplemented

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue35712>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to