On 2/17/2014 7:25 AM, M.-A. Lemburg wrote:
On 17.02.2014 13:12, Nick Coghlan wrote:
On 17 Feb 2014 21:15, "M.-A. Lemburg" <m...@egenix.com> wrote:

On 15.02.2014 07:03, Stephen J. Turnbull wrote:
M.-A. Lemburg writes:

  > IMO, it was a mistake to have None return a TypeError in
  > comparisons, since it makes many typical data operations
  > fail, e.g.

I don't understand this statement.  The theory is that they *should*
fail.

The example of sort is a good one.  Sometimes you want missing values
to be collected at the beginning of a list, sometimes at the end.
Sometimes you want them treated as top elements, sometimes as bottom.
And sometimes it is a real error for missing values to be present.
Not to mention that sometimes the programmer simply hasn't thought
about the appropriate policy.  I don't think Python should silently
impose a policy in that case, especially given that the programmer may
have experience with any of the above treatments in other contexts.

None is special in Python and has always (and intentionally) sorted
before any other object. In data processing and elsewhere in Python
programming, it's used to signal: no value available.

This is the first I've ever heard of that sorting behaviour being an
intentional feature, rather than just an artefact of Python 2 allowing
arbitrarily ordered comparisons between different types. Can you point me
to the relevant entry in the Python 2 language reference?

This is not documented anywhere in the language spec, AFAIK.

http://docs.python.org/2/reference/expressions.html#not-in

"The operators <, >, ==, >=, <=, and != compare the values of two objects. The objects need not have the same type. If both are numbers, they are converted to a common type. Otherwise, objects of different types always compare unequal, and are ordered consistently but arbitrarily."

http://docs.python.org/2/library/stdtypes.html#comparisons

"Objects of different types, except different numeric types and different string types, never compare equal; such objects are ordered consistently but arbitrarily"

It goes on to note the exception for complex numbers, but none for None. It continues

"CPython implementation detail: Objects of different types except numbers are ordered by their type names;"

Again, there is no exception noted for None, although, since the type name of None is 'NoneType', its behavior does not match that doc note.

I believe that CPython implementation detail was some of the arbitrary orderings changed in CPython between 1.3 and 2.7. I do not know whether other implementations all mimicked CPython or not, but the reference manual does not require that.

It is documented in the code (Python 2.7; Object/object.c):

default_3way_compare(PyObject *v, PyObject *w)

This is the 'final fallback' for comparisons, not the first thing tried.

...
     /* None is smaller than anything */

Reading CPython C code is not supposed to be a requirement for programming in Python. If that comment were true, I would regard it as only documenting a version of CPython, not the language standard. But it is not even true in 2.7.6. But it is not even true.

>>> class Bottom(object):  # get same results below without 'object'
        def __lt__(self, other):
                return True
        
# the following two results are consistent and
# contradict the claim that 'None is smaller than anything'
>>> Bottom() < None
True
>>> cmp(Bottom(), None)
-1

# the following two results are not consistent with the
# definition of cmp, so 1 of the 2 is buggy
>>> None < Bottom()
True
>>> cmp(None, Bottom())
1

It appears that 'anything' needs to be qualified as something like 'anything that does not itself handle comparison with None or is not given a chance to do so in a particular comparison expression'.

     if (v == Py_None)
         return -1;
     if (w == Py_None)
         return 1;

Note that it's not important whether None is smaller or greater
than any other object. The important aspect is that it's sorting
order is consistent and doesn't raise a TypeError when doing an
ordered comparison with other objects.

I can agree that it might have been nice if None had been defined as a universal bottom object, but it has not been so defined and it did not act as such. To make it (or anything else) a true bottom object would require a change in the way comparisons are evaluated. Comparisons with 'bottom' would have to be detected and special-cased at the beginning of the code, not at the end as a fallback.

--
Terry Jan Reedy

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to