Comparison Operators
Test equality, inequality, and order, plus chain comparisons in a single expression.
- Use ==, !=, <, <=, >, >= to compare values
- Chain comparisons like 0 <= x < 10
- Understand how == differs from is
- Compare values of different types
The computer, asked to decide
An evaluation 2 + 3 produces a number. But most of what a program needs to know is not a number, it is a decision. Is the score passing? Is the username taken? Is the temperature within range? Comparison operators are the branch of the arithmetical family that produces an answer out of the set instead of out of .
The six comparison operators
Each compares two values and yields a bool:
5 == 5 # True — equal
5 != 3 # True — not equal
5 < 10 # True — less than
5 <= 5 # True — less than or equal
5 > 10 # False — greater than
5 >= 5 # True — greater than or equalIn mathematics you would write these as , , ; Python opts for the ASCII-friendly <=, >=, !=. The meaning is unchanged. The double-equals == requires a deliberate pause: it is the question “are these equal?”, while a single = is an order to assign. The doubled sign is what prevents them from ever colliding.
Chain comparisons like a mathematician
Suppose belongs to the interval . On paper you write the three-part condition in one breath, . Python lets you write it exactly that way:
x = 5
0 <= x < 10 # True — both conditions hold
0 <= x < 3 # False — the second failsThis is a single expression, evaluated by the same pairing you would read: and then , except the middle value is computed only once. Chained comparison is the same as and , but the chained form reads like the mathematics it came from.
== asks about content; is asks about identity
Two questions sound alike and answer differently:
a = [1, 2, 3]
b = [1, 2, 3]
a == b # True — same content
a is b # False — different objects in memory
c = a
a is c # True — the same object== compares the values carried; is compares the memory locations. There are several boxes that happen to hold the same list; there is only one object. The two coincide for small things (like Python’s cached small integers) and diverge for everything else, so the rule of thumb is steady: use == for content, and reserve is for the single singleton which has no content to compare, None:
if x is None: # correct
if x == None: # works, but you are asking the wrong questionComparing across types
Bringing values of different sets into a comparison, versus , follows a fixed policy:
5 == 5.0 # True — numeric equality is type-ignorant
"5" == 5 # False — a string and an int are never equal
"5" < 6 # TypeError: '<' not supported between str and intTwo rules fall out. For equality, numeric values compare by worth, not by type, while values of unrelated kinds are simply never equal. For ordering, Python refuses to guess: there is no total order that makes sense between a string and an integer, so it raises TypeError rather than invent one.
A worked example: the receipt’s tolerance
The float-noise pitfall has a constructive answer. Compare within a tolerance the way a physicist would, or switch to exact whole units:
expected = 0.3
price = 0.1 + 0.2 # 0.30000000000000004
price == expected # False — float noise
abs(price - expected) < 1e-9 # True — within toleranceThe pattern is a pair of questions and a decision: are they exactly equal? False. Are they within a reasonable proximity? True. The second question is the one the real world usually means.
Common pitfalls
=vs==.if score = 60:is a syntax error, Python will not let you assign inside a condition by accident. The doubled sign is a guardrail, not a formality.- Floating-point equality.
0.1 + 0.2 == 0.3isFalse. The binary representation of is infinite, so the sum lands at . Compare within a tolerance instead:abs((0.1 + 0.2) - 0.3) < 1e-10. ==withNone.x == Nonehappens to work;x is Noneis the question you actually mean.- Float equality needs a tolerance; money needs whole units.
0.1 + 0.2 == 0.3fails (False), so either compare withinabs(a - b) < 1e-9or count in cents,120 == 12 * 10is exact.
🧩 Challenges
🧩 Challenge, think first, then reveal
Predict each result without running: 5 == 5.0, "5" == 5, 5 < "6".
💡 Answer: 5 == 5.0 → True (numeric equality across types), "5" == 5 → False (a string is never equal to an int), 5 < "6" → TypeError (ordering is not defined between int and str in Python 3).
🧩 Challenge, think first, then reveal
Write a single chained comparison that checks whether a number lies in , without using and.
💡 Answer: 1 <= n <= 100, the chained form reads exactly like the mathematical interval $1 \leq n \leq 100$.
🧩 Challenge, think first, then reveal
Why does 0.1 + 0.2 == 0.3 evaluate to False? How would you write a correct floating-point equality test?
💡 Answer: Neither $0.1$ nor $0.2$ has an exact binary representation, so their sum is $0.30000000000000004$, not exactly $0.3$. Test within a tolerance: abs((0.1 + 0.2) - 0.3) < 1e-10.
🤔 Socratic Questions
- If
a == bisTrue, musta is bbeTruetoo? In what circumstances can two objects be equal in content yet distinct in identity? - Why does Python forbid
5 < "6"yet allow5 == "5"to beFalse? What design principle keeps both behaviors consistent? - When is
isgenuinely the right tool for equality? Think about the singletonNone, and why comparing content there is meaningless.
✅ Quick check
1. What is 5 == 5.0?
2. What does 0 <= 5 < 10 evaluate to?
3. Which is the Pythonic way to check if x is None?