Custom class order: no errors, why do I need Python testing?

Without specifying the comparison properties of object comparison comparisons, Python still does something when using > and < . What is Python actually comparing these objects if you don't specify __gt__ or __lt__ ? I would expect an unsupported operand error here, as you are trying to add two objects together without dropping __add__ .

 In [1]: class MyObject(object): ...: pass ...: In [2]: class YourObject(object): ...: pass ...: In [3]: me = MyObject() In [4]: you = YourObject() In [5]: me > you Out[5]: False In [6]: you > me Out[6]: True 
+8
python object comparison-operators
source share
3 answers

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() 
+6
source share

EDIT: see update after reading! The completely correct answer is "undefined, but consistent."

It tests repr(me) vs repr(you) , which essentially does string comparisons. Here is a simple example:

 class A(object): pass class B(object): pass x = A() # <__main__.A object at 0x7f7014e4e2d0> y = B() # <__main__.B object at 0x7f7014e4e310> z = A() # <__main__.A object at 0x7f7014e4e390> x < z < y # True (assuming that the memory addresses are ordered as above) 

I agree that seems a little strange to me. Perhaps there is a good reason for this that I do not know about?

UPDATE : I am wrong about repr , although it looks like it uses the base object repr in the test. http://docs.python.org/2/reference/expressions.html#not-in

There is a line that says: "The choice of whether one object is considered smaller or larger than another is made arbitrarily, but sequentially within one program execution." In other words, it can use repr , but this is not guaranteed. However, this will be done sequentially.

+4
source share

Python uses the repr() object if there are no rich comparison operators. (At least this is true for Py2, I don't know for Py3).

So if you do

 class A(object): pass class B(object): pass l = [A() if i % 2 else B() for i in range(1000)] l.sort() 

objects are sorted by their repr() , first A() , and then B() .

0
source share

All Articles