How Does Python 2 Compare String and Int? Why Do Lists Compare as Greater Than Numbers, and Tuples Greater Than Lists

How does Python 2 compare string and int? Why do lists compare as greater than numbers, and tuples greater than lists?

From the python 2 manual:

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.

When you order two strings or two numeric types the ordering is done in the expected way (lexicographic ordering for string, numeric ordering for integers).

When you order a numeric and a non-numeric type, the numeric type comes first.

>>> 5 < 'foo'
True
>>> 5 < (1, 2)
True
>>> 5 < {}
True
>>> 5 < [1, 2]
True

When you order two incompatible types where neither is numeric, they are ordered by the alphabetical order of their typenames:

>>> [1, 2] > 'foo'   # 'list' < 'str' 
False
>>> (1, 2) > 'foo' # 'tuple' > 'str'
True

>>> class Foo(object): pass
>>> class Bar(object): pass
>>> Bar() < Foo()
True

One exception is old-style classes that always come before new-style classes.

>>> class Foo: pass           # old-style
>>> class Bar(object): pass # new-style
>>> Bar() < Foo()
False

Is this behavior mandated by the language spec, or is it up to implementors?

There is no language specification. The language reference says:

Otherwise, objects of different types always compare unequal, and are ordered consistently but arbitrarily.

So it is an implementation detail.

Are there differences between any of the major Python implementations?

I can't answer this one because I have only used the official CPython implementation, but there are other implementations of Python such as PyPy.

Are there differences between versions of the Python language?

In Python 3.x the behaviour has been changed so that attempting to order an integer and a string will raise an error:

>>> '10' > 5
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
'10' > 5
TypeError: unorderable types: str() > int()

Python2 comparing tuple and int?

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).)

How does tuple comparison work in Python?

Tuples are compared position by position:
the first item of the first tuple is compared to the first item of the second tuple; if they are not equal (i.e. the first is greater or smaller than the second) then that's the result of the comparison, else the second item is considered, then the third and so on.

See Common Sequence Operations:

Sequences of the same type also support comparisons. In particular, tuples and lists are compared lexicographically by comparing corresponding elements. This means that to compare equal, every element must compare equal and the two sequences must be of the same type and have the same length.

Also Value Comparisons for further details:

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).

If not equal, the sequences are ordered the same as their first differing elements. For example, cmp([1,2,x], [1,2,y]) returns the same as cmp(x,y). If the corresponding element does not exist, the shorter sequence is considered smaller (for example, [1,2] < [1,2,3] returns True).

Note 1: < and > do not mean "smaller than" and "greater than" but "is before" and "is after": so (0, 1) "is before" (1, 0).

Note 2: tuples must not be considered as vectors in a n-dimensional space, compared according to their length.

Note 3: referring to question https://stackoverflow.com/questions/36911617/python-2-tuple-comparison: do not think that a tuple is "greater" than another only if any element of the first is greater than the corresponding one in the second.

comparing a list against an int in Python

One could think Python 2 compares names alphabetically:

print(list>int)  # True
print(set>list) # True
print(float<int) # True

until you try

print(dict<list) # False 

Then you need to read the documentation: 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.

(emphasis mine)

This allows your to do:

k = [ 1, "a", 'c', 2.4, {1:3}, "hallo", [1,2,3], [], 4.92, {}]  # wild mix of types
k.sort() # [1, 2.4, 4.92, {}, {1: 3}, [], [1, 2, 3], 'a', 'c', 'hallo'] type-sorted

In python 3 you get

TypeError: '>' not supported between instances of ... and ...



  • http://pythonclock.org

How to compare string and integer in python?

Convert the string to an integer with int:

hours = int("14")

if (hours > 14):
print "yes"

In CPython2, when comparing two non-numerical objects of different types, the comparison is performed by comparing the names of the types. Since 'int' < 'string', any int is less than any string.

In [79]: "14" > 14
Out[79]: True

In [80]: 14 > 14
Out[80]: False

This is a classic Python pitfall. In Python3 this wart has been corrected -- comparing non-numerical objects of different type raises a TypeError by default.

As explained in the docs:

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.



Related Topics



Leave a reply



Submit