Mailing List Archive

The order of operands in the comparison
Usually the order of operands of the == operator does not matter. bool(a
== b) should return the same as bool(b == a). Correct __eq__ should look
like:

def __eq__(self, other):
if not know how to compare with other:
return NotImplemented
return the result of comparison

But we work with non-perfect code written by non-perfect people.
__eq__() can return False instead of NotImplemented for comparison with
different type (it is not the worst case, in worst case it raises
AttributeError or TypeError). So the order of operands can matter.

See https://bugs.python.org/issue37555 as an example of a real world issue.

The typical implementation of the __contains__ method looks like:

def __contains__(self, needle):
for item in self:
if item == needle: # or needle == item
return True
return False

The question is where the needle should be: at the right or at the left
side of ==?

In __contains__ implementations in list, tuple and general iterators
(see PySequence_Contains) the needle is at the right side. But in
count(), index() and remove() it is at the left side. In array it is
effectively always at the left side since its __eq__ is not invoked.

The question is whether we should unify implementations and always use
the needle at some particular side and what this side should be.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/VSV4K4AOKM4CBQMOELPFV5VMYALPH464/
Re: The order of operands in the comparison [ In reply to ]
In an ideal world, needle is on the right. Let's replace needle with a
constant: which of the following looks more natural?

for x in sequence:
if x == 5: return True

or

for x in sequence:
if 5 == x: return True

For me, 'x == 5' wins with a huge margin. (There is a subculture of C
coders who have trained themselves to write '5 == x' because they're afraid
of accidentally typing 'x = 5', but that doesn't apply to Python.)

Should we unify the stdlib? I'm not sure -- it feels like a sufficiently
obscure area that we won't get much benefit out of it (people should fix
their __eq__ implementation to properly return NotImplemented) and changing
it would surely cause some mysterious breakage in some code we cannot
control.

--Guido

On Sat, Jul 20, 2019 at 7:31 AM Serhiy Storchaka <storchaka@gmail.com>
wrote:

> Usually the order of operands of the == operator does not matter. bool(a
> == b) should return the same as bool(b == a). Correct __eq__ should look
> like:
>
> def __eq__(self, other):
> if not know how to compare with other:
> return NotImplemented
> return the result of comparison
>
> But we work with non-perfect code written by non-perfect people.
> __eq__() can return False instead of NotImplemented for comparison with
> different type (it is not the worst case, in worst case it raises
> AttributeError or TypeError). So the order of operands can matter.
>
> See https://bugs.python.org/issue37555 as an example of a real world
> issue.
>
> The typical implementation of the __contains__ method looks like:
>
> def __contains__(self, needle):
> for item in self:
> if item == needle: # or needle == item
> return True
> return False
>
> The question is where the needle should be: at the right or at the left
> side of ==?
>
> In __contains__ implementations in list, tuple and general iterators
> (see PySequence_Contains) the needle is at the right side. But in
> count(), index() and remove() it is at the left side. In array it is
> effectively always at the left side since its __eq__ is not invoked.
>
> The question is whether we should unify implementations and always use
> the needle at some particular side and what this side should be.
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-leave@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/VSV4K4AOKM4CBQMOELPFV5VMYALPH464/
>


--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him/his **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: The order of operands in the comparison [ In reply to ]
There's also bisect_left and bisect_right which each do different things.
The bisect_left function puts the needle on the right while the
bisect_right function puts the needle on the left.

I've thought a bit about these scenarios as the author of Sorted Containers
but no user has ever raised an issue about it. Personally, I think the
needle should go on the left as it offers the caller greater opportunity to
control and customize the __eq__ method that is used.

But personal preferences aside, I think the "ship has sailed" and the
differences are not worth fixing. I agree with Guido that developers should
fix __eq__ to use NotImplemented as it was intended.

Grant


On Sat, Jul 20, 2019 at 8:33 AM Guido van Rossum <guido@python.org> wrote:

> In an ideal world, needle is on the right. Let's replace needle with a
> constant: which of the following looks more natural?
>
> for x in sequence:
> if x == 5: return True
>
> or
>
> for x in sequence:
> if 5 == x: return True
>
> For me, 'x == 5' wins with a huge margin. (There is a subculture of C
> coders who have trained themselves to write '5 == x' because they're afraid
> of accidentally typing 'x = 5', but that doesn't apply to Python.)
>
> Should we unify the stdlib? I'm not sure -- it feels like a sufficiently
> obscure area that we won't get much benefit out of it (people should fix
> their __eq__ implementation to properly return NotImplemented) and changing
> it would surely cause some mysterious breakage in some code we cannot
> control.
>
> --Guido
>
> On Sat, Jul 20, 2019 at 7:31 AM Serhiy Storchaka <storchaka@gmail.com>
> wrote:
>
>> Usually the order of operands of the == operator does not matter. bool(a
>> == b) should return the same as bool(b == a). Correct __eq__ should look
>> like:
>>
>> def __eq__(self, other):
>> if not know how to compare with other:
>> return NotImplemented
>> return the result of comparison
>>
>> But we work with non-perfect code written by non-perfect people.
>> __eq__() can return False instead of NotImplemented for comparison with
>> different type (it is not the worst case, in worst case it raises
>> AttributeError or TypeError). So the order of operands can matter.
>>
>> See https://bugs.python.org/issue37555 as an example of a real world
>> issue.
>>
>> The typical implementation of the __contains__ method looks like:
>>
>> def __contains__(self, needle):
>> for item in self:
>> if item == needle: # or needle == item
>> return True
>> return False
>>
>> The question is where the needle should be: at the right or at the left
>> side of ==?
>>
>> In __contains__ implementations in list, tuple and general iterators
>> (see PySequence_Contains) the needle is at the right side. But in
>> count(), index() and remove() it is at the left side. In array it is
>> effectively always at the left side since its __eq__ is not invoked.
>>
>> The question is whether we should unify implementations and always use
>> the needle at some particular side and what this side should be.
>> _______________________________________________
>> Python-Dev mailing list -- python-dev@python.org
>> To unsubscribe send an email to python-dev-leave@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/VSV4K4AOKM4CBQMOELPFV5VMYALPH464/
>>
>
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him/his **(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-leave@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/WRNIZS3E4NO74JDANPGPX2JZEDHOTPFC/
>
Re: The order of operands in the comparison [ In reply to ]
FWIW, the bisect_left and bisect_right functions have different argument order so that they can both use __lt__, making them consistent with sorting and with the heapq functions.

Raymond
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/O2AETKAY5EVLIQNRRSFV53NQ6K3TF5EN/
Re: The order of operands in the comparison [ In reply to ]
20.07.19 18:26, Guido van Rossum ????:
> In an ideal world, needle is on the right. Let's replace needle with a
> constant: which of the following looks more natural?
>
>   for x in sequence:
>       if x == 5: return True
>
> or
>
>   for x in sequence:
>       if 5 == x: return True
>
> For me, 'x == 5' wins with a huge margin. (There is a subculture of C
> coders who have trained themselves to write '5 == x' because they're
> afraid of accidentally typing 'x = 5', but that doesn't apply to Python.)
>
> Should we unify the stdlib? I'm not sure -- it feels like a sufficiently
> obscure area that we won't get much benefit out of it (people should fix
> their __eq__ implementation to properly return NotImplemented) and
> changing it would surely cause some mysterious breakage in some code we
> cannot control.

Thank you. The majority of the code uses needle on the right. There are
just 6 places where it is on the left, and the half of them look
copy-pasted, and in one place the C code differs from the corresponding
Python implementation. There is an order more places where needle is on
the right (and it is always on the right in the Python code). So I
prefer to fix these few places to get rid of the minor inconsistency.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/VOE23UOO33ZPHWJNNX6QHEPBQVJ7VTIS/
Re: The order of operands in the comparison [ In reply to ]
Serhiy Storchaka wrote:
> Thank you. The majority of the code uses needle on the right. There are
> just 6 places where it is on the left, and the half of them look
> copy-pasted, and in one place the C code differs from the corresponding
> Python implementation. There is an order more places where needle is on
> the right (and it is always on the right in the Python code). So I
> prefer to fix these few places to get rid of the minor inconsistency.

If there are only a few places where the needle is on the left and there's not a specific functionality requirement/limitation in those locations which prevent it from being on the right, it's better to have consistency. Is there any particular benefit from having the needle on the left side, or was it just a personal preference from the developer who first implemented the code in those 6 locations?
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/JYQ5YFUWLGULRUX5T36KD6EJEKKY3L22/
Re: The order of operands in the comparison [ In reply to ]
22.07.19 11:04, Kyle Stanley ????:
> Serhiy Storchaka wrote:
>> Thank you. The majority of the code uses needle on the right. There are
>> just 6 places where it is on the left, and the half of them look
>> copy-pasted, and in one place the C code differs from the corresponding
>> Python implementation. There is an order more places where needle is on
>> the right (and it is always on the right in the Python code). So I
>> prefer to fix these few places to get rid of the minor inconsistency.
>
> If there are only a few places where the needle is on the left and there's not a specific functionality requirement/limitation in those locations which prevent it from being on the right, it's better to have consistency. Is there any particular benefit from having the needle on the left side, or was it just a personal preference from the developer who first implemented the code in those 6 locations?

See https://bugs.python.org/issue37648.

Seems somebody once wrote the code for list.__contains__, and then it
was copied to other places. The code in _asynciomodule.c might be
independent, but it is inconsistent with the Python code.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/5TX2LX4NIYJ3EHWGQSZ2M7FKGJ2XPLU7/