Comparison Operators
Comparison operators ask a question about two values and return a boolean answer: True or False. They're the building blocks of every if statement, while loop condition, and filter you'll write. Python supports the six comparisons you'd expect from any language, but it also adds a genuinely distinctive feature — chained comparisons — and enforces stricter rules than many languages about which types can be compared at all.
The six comparison operators
Operator | Meaning | Example | Result |
|---|---|---|---|
| Equal to |
|
|
| Not equal to |
|
|
| Greater than |
|
|
| Less than |
|
|
| Greater than or equal to |
|
|
| Less than or equal to |
|
|
Chained comparisons — a distinctly Pythonic feature
Most languages don't let you write 1 < x < 10 and have it mean what you'd hope. In C, Java, or JavaScript, that expression is evaluated left to right: (1 < x) < 10 first computes a boolean (True or False, i.e. 1 or 0), and then compares that to 10 — which is almost always True, regardless of what x actually is.
Python special-cases this pattern. A chained comparison like a < b < c is evaluated as a < b and b < c, with b evaluated only once, short-circuiting if the first part is false. This reads naturally and matches how you'd write the inequality in math class.
Chained comparison vs. the naive translation
x = 15 # Pythonic chained comparison — this is what you actually want: print(1 < x < 10) # False, because x (15) is not less than 10 # What it's really doing under the hood: print(1 < x and x < 10) # False -- same result # Compare that to what a C-style language would do if < just # chained left-to-right on booleans. We can simulate that here: result_of_first = (1 < x) # True naive = result_of_first < 10 # True < 10 -> True (bool is a subclass of int) print(naive) # True -- very different answer!
False False True
This isn't just a toy example — it proves the two interpretations genuinely disagree for x = 15. Python's chained form correctly reports False (15 is not between 1 and 10), while naively re-applying < to a boolean result gives the misleading True. You can chain as many comparisons as you like, e.g. 0 <= score <= 100, and even mix operators, e.g. a < b <= c != d.
Comparing different types
Python 2 allowed comparing almost any two objects with < or > (using an arbitrary but consistent ordering), which quietly hid bugs. Python 3 tightened this up: comparing genuinely incompatible types with ordering operators raises a TypeError. Equality checks (==, !=) are more forgiving — comparing unrelated types with == simply returns False rather than raising.
Ordering incompatible types raises TypeError
print(5 == "5") # False -- no error, just not equal print(5 != "5") # True print(5 < "5") # raises TypeError # Traceback (most recent call last): # ... # TypeError: '<' not supported between instances of 'int' and 'str'
False True Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'int' and 'str'
Comparing strings lexicographically
Strings compare character by character using Unicode code point values, the same way you'd alphabetize words in a dictionary — this is called lexicographic ordering. Comparison stops at the first differing character; if one string is a prefix of the other, the shorter string is considered smaller.
print("apple" < "banana") # True -- 'a' < 'b'
print("apple" < "apply") # True -- differ at 5th char, 'e' < 'y'
print("Zebra" < "apple") # True -- 'Z' (90) has a lower code point than 'a' (97)
print("app" < "apple") # True -- "app" is a prefix, so it's "smaller"Comparing custom objects
By default, comparing two instances of a class you wrote with == checks identity (same as is), because Python doesn't know what "equal" means for your data unless you tell it. You can customize this behavior by defining the __eq__ method (and __lt__, __gt__, and friends for ordering).