For objects, an arbitrary order is imposed. Ordering is defined only as stable program execution .
This means that prior to the Python implementation, you can determine the order when comparing arbitrary objects. CPython uses the memory address if the types are the same (from C-source ):
if (v->ob_type == w->ob_type) { /* When comparing these pointers, they must be cast to * integer types (ie Py_uintptr_t, our spelling of C9X's * uintptr_t). ANSI specifies that pointer compares other * than == and != to non-related structures are undefined. */ Py_uintptr_t vv = (Py_uintptr_t)v; Py_uintptr_t ww = (Py_uintptr_t)w; return (vv < ww) ? -1 : (vv > ww) ? 1 : 0; }
The same value is the basis for the id() function and is also presented in the repr() by default for custom classes, so it might seem that the repr() classes defines the order. This is only the memory address that does.
For objects that are not the same type, the type name is used instead (with the number type sorted before the others), and if the types are different, but their names are the same, the code returns to the type memory address (unlike the instance memory address, when the types are the same).
This implicit ordering is considered a bug in the language and has been fixed in Python 3 :
Order comparison operators ( < , <= , >= , > ) throw a TypeError exception when the operands do not have meaningful natural ordering.
This applies to custom classes that do not implement the necessary ordering hooks :
>>> class Foo(): pass ... >>> Foo() < Foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: Foo() < Foo()
Martijn pieters
source share