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:
| Operator | Meaning | Example | Result |
|---|---|---|---|
| == | Equal value | 5 == 5 | True |
| != | Not equal value | 5 != 3 | True |
| < | Strictly less than | 3 < 5 | True |
| > | Strictly greater than | 5 > 3 | True |
| <= | Less than or equal | 5 <= 5 | True |
| >= | Greater than or equal | 5 >= 5 | True |
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.
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
Key Insights
- Six comparison operators: ==, !=, <, >, <=, >=. All return True or False.
- Chained comparisons like
0 < x < 10evaluate 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.
Frequently Asked Questions
Can I compare values of different types in Python?
What are chained comparisons in Python?
Can complex numbers be compared with ordering operators?
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.
More in this topic
Create and Assign Variables in Python
Learn every way to create and assign variables in Python, from basic single assignment to expressions, type hints, and practical patterns beginners use every day.
Python Variable Naming Rules
Learn Python's variable naming rules, including allowed characters, reserved keywords, PEP 8 conventions, and how to choose names that make your code readable.
Python Variables Explained
Understand what Python variables are, how they store and reference data, and why Python's variable model is different from other programming languages.