On 24.01.2020 5:36, Guido van Rossum wrote:
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.

This cannot be an implementation detail because it changes the outcome of 
operations.
Without it, things like `math.nan in seq` would always return False.
So it's not even an "optimization" but rather "behavior".

IMO a user should not rely on __eq__ to be called at any time so we shouldn't 
document that it could be skipped or whatever.

Instead, we should document that `in` (and whatever other public API uses PyObject_RichCompareBool) compares by identity first (and this is intended because `math.nan in seq` returning True if there are NaNs is more practical in the general case).


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 
<mailto: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 
<mailto:python-dev@python.org>
    To unsubscribe send an email to python-dev-le...@python.org 
<mailto: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 <http://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/

--
Regards,
Ivan

_______________________________________________
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/YKZYSRV2MJRBSMOBXB2BROKJIGLAN37U/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to