On 09Jul2014 07:00, Steven D'Aprano <st...@pearwood.info> wrote:
At the moment, Python has two (in)equality operators, == and != which
call __eq__ and __ne__ methods. Some problems with those:

* Many people expect == to always be reflexive (that is, x == x for
 every x) but classes which customise __eq__ may not be.

I'm presuming this proposal is fallout from the Nan anecdotes, since NaN != Nan?

The language spec is at least up front about it, I thought. It could be plainer, but at least it says:

Furthermore, some types (for example, function objects) support only a degenerate notion of comparison where any two objects of that type are unequal.

which implies nonreflexivity.

Returning to Nan, I had thought it was an explicit design choice in IEEE floating point that NaN != NaN so that in (hypothetically) common cases results won't accidentally issue truthiness in the vein of propagating evaluation errors.

Personally I'd go for Nan == Nan raising a ValueError myself, but that is a bikeshed I lack the expertise to paint.

Anyway, I thought it is a design feature that a class can arrange for nonreflexivity in ==. Surprising, maybe, but wouldn't use of such a special class be known to the user?

Have we got some examples of people using nonreflexive == classes and being burnt? Aside from Nan, which I'd argue is a well known special case, or should be.

* The == operator requires __eq__ to return True or False
 (or NotImplemented) and raises TypeError if it doesn't, which
 makes it impossible to use == with (say) three-valued or fuzzy
 logic.

In the Python 3.4.0 docs the __eq__ etc methods have this paragraph:

A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.

and some tests with 2.7.8 and 3.4.1:

    % python
    Python 2.7.8 (default, Jul  3 2014, 06:13:58)
    [GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> class O(object):
    ...   def __eq__(self, other): return 9
    ...
    >>> o=O()
    >>> o == o
    9

    % python3.4
    Python 3.4.1 (default, May 21 2014, 01:39:38)
    [GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> class O(object):
    ...   def __eq__(self, other): return 9
    ...
    >>> o=O()
    >>> o == o
    9

I don't see this type constraint you describe.

I propose:

* The == operator be redefined to *always* assume reflexivity, that
 is, it first compares the two arguments using `is` before calling
 the __eq__ methods.

Won't this slow down every == test?

* That's a backwards-incompatible change, so you need to enable it
 using "from __future__ import equals" in Python 3.5, and then to
 become the default behaviour in 3.6.

* To support non-reflexive types, allow === and !=== operators, which
 are like == and != except they don't call `is` first.
[...]

I don't like the spelling. They seem very easy to misuse as typos of conventional == and !=, and not visually very different.

Cheers,
Cameron Simpson <c...@zip.com.au>

55 mph is fast enough to get you killed, but slow enough to make you think
you're safe.    - The Gumball Rally
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to