Search code examples
pythonpython-3.xtuplescomparisonpython-2.x

Python2 comparing tuple and int?


I'm currently porting some Python2 code to Python3, and I've encountered this little gem:

v = (1, )
if v < 1:
    pass

Now, in Python3 it throws an error:

TypeError: '<' not supported between instances of 'tuple' and 'int'.

Which is fine, since you cannot compare tuples and integers. But in Python2 this is allowed:

>>> (1, ) < 1
    False

I've googled, but can't find an example of how this comparison works. How/why does the above example evaluate to False?


Solution

  • The difference in behavior is described in the docs:

    https://docs.python.org/2/library/stdtypes.html#comparisons

    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). Furthermore, some types (for example, file objects) support only a degenerate notion of comparison where any two objects of that type are unequal. Again, such objects are ordered arbitrarily but consistently. The <, <=, > and >= operators will raise a TypeError exception when any operand is a complex number.


    As you already noticed, comparing tuples and integers no longer work in Python 3, due to some changes in the comparison mechanics:

    https://docs.python.org/3.0/whatsnew/3.0.html#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.
    • builtin.sorted() and list.sort() no longer accept the cmp argument providing a comparison function. Use the key argument instead. N.B. the key and reverse arguments are now “keyword-only”.
    • The cmp() function should be treated as gone, and the cmp() special method is no longer supported. Use lt() for sorting, eq() with hash(), and other rich comparisons as needed. (If you really need the cmp() functionality, you could use the expression (a > b) - (a < b) as the equivalent for cmp(a, b).)