[Python-Dev] PyObject_RichCompareBool identity shortcut (original) (raw)

Nick Coghlan ncoghlan at gmail.com
Wed Apr 27 17:31:15 CEST 2011


On Thu, Apr 28, 2011 at 12:53 AM, Guido van Rossum <guido at python.org> wrote:

What surprises me is that anyone gets surprised by anything when experimenting with an object that isn't equal to itself.  It is roughly in the same category as creating a hash that has no relationship to eq or making self-referencing sets or setting False,True=1,0 in python 2.  See http://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civilization/ for a nice blog post on the subject. Maybe we should just call off the odd NaN comparison behavior?

Rereading Meyer's article (I read it last time this came up, but it's a nice piece, so I ended up going over it again this time) the quote that leapt out at me was this one:

"""A few of us who had to examine the issue recently think that — whatever the standard says at the machine level — a programming language should support the venerable properties that equality is reflexive and that assignment yields equality.

Every programming language should decide this on its own; for Eiffel we think this should be the specification. Do you agree?"""

Currently, Python tries to split the difference: "==" and "!=" follow IEEE754 for NaN, but most other operations involving builtin types rely on the assumption that equality is always reflexive (and IEEE754 be damned).

What that means is that "correct" implementations of methods like contains, eq, ne, index() and count() on containers should be using "x is y or x == y" to enforce reflexivity, but most such code does not (e.g. our own collections.abc.Sequence implementation gets those of these that it implements wrong, and hence Sequence based containers will handle NaN in a way that differs from the builtin containers)

And none of that is actually documented anywhere (other than a behavioural note in the 3.x documentation for PyObject_RichCompareBool), so it's currently just an implementation detail of CPython that most of the builtin containers behave that way in practice.

Given the status quo, what would seem to be the path of least resistance is to:

Types with a non-reflexive notion of equality still wouldn't play nicely with containers that didn't enforce reflexivity where appropriate, but bad interactions between 3rd party types isn't really something we can prevent.

Backing away from having float and decimal.Decimal respect the IEEE754 notion of NaN inequality at this late stage of the game seems like one for the "too hard" basket. It also wouldn't achieve much, since we want the builtin containers to preserve their invariants even for 3rd party types with a non-reflexive notion of equality.

Cheers, Nick.

-- Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-Dev mailing list