74

Is there a Python built-in datatype, besides None, for which:

>>> not foo > None
True

where foo is a value of that type? How about Python 3?

Attila O.
  • 13,553
  • 9
  • 51
  • 82

2 Answers2

92

None is always less than any datatype in Python 2 (see object.c).

In Python 3, this was changed; now doing comparisons on things without a sensible natural ordering results in a TypeError. From the 3.0 "what's new" updates:

Python 3.0 has simplified the rules for ordering comparisons:

The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering. Thus, expressions like: 1 < '', 0 > None or len <= len are no longer valid, and e.g. None < None raises TypeError instead of returning False. A corollary is that sorting a heterogeneous list no longer makes sense – all the elements must be comparable to each other. Note that this does not apply to the == and != operators: objects of different incomparable types always compare unequal to each other.

This upset some people since it was often handy to do things like sort a list that had some None values in it, and have the None values appear clustered together at the beginning or end. There was a thread on the mailing list about this a while back, but the ultimate point is that Python 3 tries to avoid making arbitrary decisions about ordering (which is what happened a lot in Python 2).

Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
John Feminella
  • 281,997
  • 42
  • 326
  • 347
  • 1
    Thanks for clarifying the state of Python 3. I remember reading the "what's new" page but I don't remember this one. Very interesting, but it makes sense indeed... – Attila O. Feb 06 '10 at 19:31
  • 2
    Of course, there's nothing arbitrary about ordering None, as long as it's clearly defined. This sort of gratuitous incompatibility is why Python 3 adoption is taking so long. – Glenn Maynard Feb 07 '10 at 01:39
  • 13
    "Well-defined" (clear, explicit definition of behavior) is distinct from "arbitrary" (a choice made based on discretion). For example, one could just as easily have said "None compares greater than everything". That's equally well-defined, but still quite arbitrary. – John Feminella Feb 07 '10 at 05:46
  • 1
    Indeed it was extremely handy (e.g. input sanity checks) to allow comparisons between incomparable types, and to me it would seem logical to have such comparisons always return False - like when comparing numericals to NaN's. Unfortunately, this was not the case (e.g., `None<0` returning `True`), and apparently in Python 3 this is handled by forbidding such comparisons altogether - a huge 'improvement' indeed ...! ;-) – Rolf Bartstra Dec 06 '12 at 14:55
  • 2
    Having None compare less than everything feels much less arbitrary than having it compare greater than everything. Empty strings come before any other string, 'zero' comes before any positive integer, so intuitively, the None type comes before any other type. – HorseloverFat Feb 09 '13 at 16:27
  • @GlennMaynard: Yes, ordering None in a list of numbers is arbitrary, because it's not a number. Currently, `if parameter < 0` doesn't work if `parameter=None` by default, which is stupid. You can always do `key=lambda x: float('-inf') if x is None else x` or `key=lambda x: float('inf') if x is None else x` or `key=lambda x: 0 if x is None else x`, depending on which arbitrary ordering you prefer. – endolith Apr 01 '13 at 14:30
30

From the Python 2.7.5 source (object.c):

static int
default_3way_compare(PyObject *v, PyObject *w)
{
    ...
    /* None is smaller than anything */
    if (v == Py_None)
            return -1;
    if (w == Py_None)
            return 1;
    ...
}

EDIT: Added version number.

Martín Coll
  • 2,522
  • 2
  • 27
  • 46
Torsten Marek
  • 74,426
  • 19
  • 88
  • 96