Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary __gt__ and __lt__ implementation

I've been experimenting with Python dictionaries and discovered that __gt__ and __lt__ are implemented for dictionaries.

I've tested them and it appears that they somehow compare the keys, but it is not quite clear to me how that is done; for example, I'm not quite sure how {1: 1} > {'0': 0} returns False (as a matter of fact, '0' > 100000 returns True as well).

Is there any document with specifics on the implementation of these two functions?

like image 289
Lorenzo Trojan Avatar asked Apr 28 '15 10:04

Lorenzo Trojan


Video Answer


1 Answers

The documentation has a section on comparisons. In particular:

Objects of different types, except different numeric types and different string types, never compare equal; such objects are ordered consistently but arbitrarily (so that sorting a heterogeneous array yields a consistent result).

The reason for behaviour like:

>>> '0' < 0
False
>>> 0 < '0'
True

in CPython is that the "consistently but arbitrarily" comparison method selected was to order alphabetically by type name, and 'str' > 'int':

CPython implementation detail: Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.

This behaviour was altered for Python 3.x and you can no longer compare heterogeneous types (or dictionaries, for that matter):

>>> '0' > 0
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    '0' > 0
TypeError: unorderable types: str() > int()
>>> {'a': None} > {'b': None}
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    {'a': None} > {'b': None}
TypeError: unorderable types: dict() > dict()

In terms of dictionaries specifically, they are sorted such that:

d1 > d2

becomes:

(len(d1) > len(d2) or 
 (len(d1) == len(d2) and
  sorted(d1.items()) > sorted(d2.items()))

(you can see this implemented in the CPython source code). So if they aren't the same length the "longer" one is "larger":

>>> {1: 2, 3: 4} > {1: 2}
True

if they have matching keys, the one with "larger" values is "larger":

>>> {1: 2} > {1: 1}
True

and if they have mismatching keys, the one with the "larger" keys is "larger":

>>> {1: 2} > {2: 1}
False
like image 198
jonrsharpe Avatar answered Oct 04 '22 17:10

jonrsharpe