When trying to compare dictionaries, python raises a TypeError:
{"a" : "b"} < {"a" : "b"} # TypeError
When trying to compare tuples, python does it elementwise:
(1, 2) > (1, 1) # True
Therefore, I expected that comparing tuples containing dictionaries would result in a TypeError if the elements preceding the dictionaries were equal because it would then be forced to compare the dictionaries, which would raise a TypeError. This is not the case:
(3, {"a" : "b"}) < (3, {"a" : "b"}) # False, no TypeError
I've read through the documentation I could find regarding Python sorting and did not see anything documenting this behavior. Can I rely on this behavior staying the same in future versions?
CodePudding user response:
This is explained in the docs:
Lexicographical comparison between built-in collections works as follows:
For two collections to compare equal, they must be of the same type, have the same length, and each pair of corresponding elements must compare equal (for example, [1,2] == (1,2) is false because the type is not the same).
Collections that support order comparison are ordered the same as their first unequal elements (for example, [1,2,x] <= [1,2,y] has the same value as x <= y). If a corresponding element does not exist, the shorter collection is ordered first (for example, [1,2] < [1,2,3] is true).
So the first thing that the tuple comparison will do is to find the unequal elements, as there are not unequal elements in your tuple the result is False
, and there is no need to call the code for <
.
This is further confirmed by looking at the implementation of the comparison of tuples:
for (i = 0; i < vlen && i < wlen; i ) {
int k = PyObject_RichCompareBool(vt->ob_item[i],
wt->ob_item[i], Py_EQ);
if (k < 0)
return NULL;
if (!k)
break;
}
if (i >= vlen || i >= wlen) {
/* No more items to compare -- compare sizes */
Py_RETURN_RICHCOMPARE(vlen, wlen, op);
}
The for loop in the code above tries to find the first unequal elements and if not found delegates the comparison to the size of the tuples.