Good question!

I think this started with a valuable optimization for `x in <list>`. I
don't know if that was ever carefully documented, but I remember that it
was discussed a few times (and IIRC Raymond was adamant that this should be
so optimized -- which is reasonable).

I'm tempted to declare this implementation-defined behavior -- *implicit*
calls to __eq__ and __ne__ *may* be skipped if both sides are the same
object depending on the whim of the implementation.

We should probably also strongly recommend that __eq__ and __ne__ not do
what math.nan does.

However we cannot stop rich compare __eq__ implementations that return
arrays of pairwise comparisons, since numpy does this. (And yes, it seems
that this means that `x in y` is computed incorrectly if x is an array with
such an __eq__ implementation and y is a tuple of such objects. I'm sure
there's a big warning somewhere in the numpy docs about this, and I presume
if y is a numpy array they make sure to do something better.)

On Thu, Jan 23, 2020 at 5:33 PM Tim Peters <tim.pet...@gmail.com> wrote:

> PyObject_RichCompareBool(x, y, op) has a (valuable!) shortcut:  if x
> and y are the same object, then equality comparison returns True and
> inequality False.  No attempt is made to execute __eq__ or __ne__
> methods in those cases.
>
> This has visible consequences all over the place, but they don't
> appear to be documented.  For example,
>
> >>> import math
> >>> ([math.nan] * 5).count(math.nan)
> 5
>
> despite that `math.nan == math.nan` is False.
>
> It's usually clear which methods will be called, and when, but not
> really here.  Any _context_ that calls PyObject_RichCompareBool()
> under the covers, for an equality or inequality test, may or may not
> invoke __eq__ or __ne__, depending on whether the comparands are the
> same object.  Also any context that inlines these special cases to
> avoid the overhead of calling PyObject_RichCompareBool() at all.
>
> If it's intended that Python-the-language requires this, that needs to
> be documented.
>
> Or if it's implementation-defined, then _that_ needs to be documented.
>
> Which isn't straightforward in either case, in part because
> PyObject_RichCompareBool isn't a language-level concept.
>
> This came up recently when someone _noticed_ the list.count(NaN)
> behavior, and Victor made a PR to document it:
>
> https://github.com/python/cpython/pull/18130
>
> I'm pushing back, because documenting it _only_ for .count() makes
> .count() seem unique in a way it isn't, and doesn't resolve the
> fundamental issue:  is this language behavior, or implementation
> behavior?
>
> Which I don't want to argue about.  But you certainly should ;-)
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/3ZAMS473HGHSI64XB3UV4XBICTG2DKVF/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/X4ZIICG2EBMYPFUASI5TW4E6PIT2KR6M/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to