Compare Values and Data Types in Python

Learn how to compare values in Python using comparison operators, chained comparisons, and how different data types behave when compared to each other.

5 min read

Comparing values is one of the most fundamental operations in any program, and Python provides a rich set of comparison operators that work consistently across all built-in types. When you write an if-statement that checks whether a score is above a threshold, a loop that runs while a counter stays below a limit, or a validation that confirms two passwords match, you are using Python's comparison system. The six comparison operators are less-than, greater-than, less-than-or-equal, greater-than-or-equal, equal, and not-equal. Every one of them returns a boolean value, True or False, which slots directly into the conditional structures that control program flow.

If you have explored the Python data types overview and understand the difference between the is operator and the double-equals operator for identity versus equality checks, this article completes your understanding of how Python decides whether values are the same, different, larger, or smaller. Comparisons might seem simple on the surface, but Python layers in several features that make them more powerful and safer than in many other languages. Chained comparisons let you write math-like range checks. Cross-type ordering restrictions prevent nonsensical comparisons from silently producing wrong answers. And the rules for which types can be compared to which other types are consistent enough that you can reason about them without memorizing a long list of exceptions.

The six comparison operators

Python provides six comparison operators, and each one takes two operands and returns a boolean. The less-than operator returns True when the left operand is strictly smaller than the right. The greater-than operator returns True when the left operand is strictly larger. The less-than-or-equal and greater-than-or-equal operators include the case where both operands are equal. The double-equals operator returns True when both operands have the same value. The not-equal operator returns True when the operands have different values. All six operators have the same precedence, which is lower than arithmetic operators but higher than boolean operators like and, or, and not.

The table below summarizes each operator with its meaning and a simple example:

OperatorMeaningExampleResult
==Equal value5 == 5True
!=Not equal value5 != 3True
<Strictly less than3 < 5True
>Strictly greater than5 > 3True
<=Less than or equal5 <= 5True
>=Greater than or equal5 >= 5True

The examples use integers for clarity, but all six operators work on any type that supports them. Strings compare lexicographically based on Unicode code points, with uppercase letters sorting before lowercase letters. Lists and tuples compare element by element, with the first differing element determining the result. Dictionaries compare equal when they contain the same key-value pairs, but they do not support ordering comparisons.

Chained conditionals

Python supports a feature that many languages do not: chained comparisons. Instead of writing 0 < x and x < 10 to check whether x lies in an exclusive range, you can write 0 < x < 10. Python evaluates this by checking each adjacent pair of operands with the operator between them and combining the results with logical and. The middle operand, x in this case, is evaluated only once, which matters if x is a function call or an expression with side effects. Chained comparisons can mix different operators, so a < b == c <= d is valid and checks that a is less than b, that b equals c, and that c is less than or equal to d.

Chaining works with all comparison operators including is and in. You can write a is not None is not b as a chained expression, though readability suffers with longer chains. The most common and most readable use of chaining is range checks, which appear frequently in validation code and data processing pipelines.

pythonpython
score = 85
if 0 <= score <= 100:
    print("Valid score")

A function that validates an exam score between 0 and 100 reads naturally as if 0 <= score <= 100 and communicates the intent more clearly than the equivalent and-based expression spread across multiple lines.

Rules for cross-type ordering

Python 3 enforces a strict rule for ordering comparisons between unrelated types. If you try to compare an integer and a string with the less-than operator, Python raises a TypeError instead of returning a result. This is a deliberate design choice that prevents the kind of silent, incorrect behavior that plagued Python 2, where different types were ordered arbitrarily by their type names. The only exceptions to this rule are numeric types, which can be compared across type boundaries because they represent the same mathematical concept. An integer and a float compare correctly. An integer and a complex number cannot be compared for ordering, but they can be compared for equality.

Equality comparisons with double-equals and not-equal work between any two types without raising an error. Comparing an integer to a string with double-equals always returns False because they are different types with different values, but Python does not consider this an error. This design means you can safely check whether any two values are equal without first verifying that they share a type, which simplifies code that handles heterogeneous data.

The types that cannot be ordered at all, even with their own kind, are limited to complex numbers and a few collection types. Complex numbers lack a total ordering because the complex plane is two-dimensional. Dictionaries cannot be ordered because there is no universally agreed meaning for one dictionary being less than another. Sets and frozen sets support subset and superset comparisons through the less-than and greater-than operators applied to sets specifically, where a < b means a is a proper subset of b, but the same operators do not establish a total ordering across arbitrary sets.

How each type handles ordering

Numbers compare as you would expect mathematically. Integers and floats interoperate seamlessly, with Python converting the integer to its float equivalent for the comparison when necessary. The integer 1 and the float 1.0 compare as equal because they represent the same quantity. The boolean values True and False compare as 1 and 0 respectively with integers and floats because bool is a numeric subclass. This numeric interoperability is convenient but requires awareness when you are checking types alongside values.

Strings compare lexicographically, character by character, using the Unicode code point of each character. This means uppercase letters sort before lowercase letters because their code points are numerically smaller. The string "Apple" is less than "apple" in Python's ordering. Digits sort before letters. The space character sorts before digits. If you need case-insensitive comparison, convert both strings to lowercase or uppercase first before comparing, or use the casefold method for a more aggressive locale-aware normalization.

Sequences like lists and tuples compare element by element from the first position to the last. Two sequences are equal if they have the same length and each corresponding pair of elements is equal. One sequence is less than another if the first differing pair of elements has the smaller value in the first sequence, or if the first sequence is a prefix of the second. Nested sequences are compared recursively, so a list of lists compares each inner list element by element. For sequences containing elements of different types, the comparison may raise a TypeError if it reaches a pair of elements that cannot be ordered against each other.

Rune AI

Rune AI

Key Insights

  • Six comparison operators: ==, !=, <, >, <=, >=. All return True or False.
  • Chained comparisons like 0 < x < 10 evaluate each adjacent pair with and logic.
  • Ordering comparisons (<, >, <=, >=) between unrelated types raise TypeError.
  • Complex numbers, dicts, and sets cannot be ordered; they only support == and !=.
  • Numeric types compare across boundaries: 1 == 1.0 is True.
RunePowered by Rune AI

Frequently Asked Questions

Can I compare values of different types in Python?

In Python 3, comparing values of unrelated types with ordering operators like less-than or greater-than raises a TypeError. For example, comparing an integer and a string with < fails because there is no meaningful ordering between numbers and text. Equality comparisons with == and != work between any types and will return False (not equal) rather than raising an error. Numeric types can be compared across type boundaries: integers and floats compare correctly because they represent the same mathematical concept.

What are chained comparisons in Python?

Chained comparisons let you write expressions like `0 < x < 10` which Python evaluates as `0 < x and x < 10`, except that x is evaluated only once. This is cleaner and more readable than the equivalent logical-and expression. Chains can include any number of comparisons: `a < b == c > d` is valid Python and evaluates each adjacent pair. Chained comparisons work with all comparison operators including ==, !=, is, and in.

Can complex numbers be compared with ordering operators?

No. Complex numbers are two-dimensional values with real and imaginary parts, and there is no mathematically consistent way to define a total ordering on the complex plane. Python raises a TypeError if you attempt to use less-than, greater-than, less-than-or-equal, or greater-than-or-equal with complex operands. Equality and inequality comparisons with == and != work correctly because they check whether both the real and imaginary parts match exactly.

Conclusion

Python's comparison system is expressive, safe, and consistent. Comparison operators return boolean results that drive conditional logic throughout your programs. Chained comparisons make range checks more readable. Cross-type ordering restrictions prevent you from accidentally comparing values that have no meaningful order. Understanding how each type behaves under comparison equips you to write conditions that are both correct and clear.