bool Comparisons¶
Comparisons test relationships between values and produce Boolean results.
These results are central to decision making in Python.
Common comparison operators include:
| Operator | Meaning |
|---|---|
== |
equal to |
!= |
not equal to |
< |
less than |
> |
greater than |
<= |
less than or equal to |
>= |
greater than or equal to |
flowchart TD
A[Two values] --> B[comparison operator]
B --> C[Boolean result]
````
!!! tip "Mental Model"
A comparison is a question that always returns `True` or `False`. `==` asks "are these values equal?" while `is` asks "are these the exact same object in memory?" Most of the time you want `==` for value equality. Comparisons are the inputs that drive `if` statements, loops, and every other decision your program makes.
---
## 1. Equality and Inequality
Equality checks whether two values are the same.
```python
print(5 == 5)
print(5 != 3)
Output:
text
True
True
These comparisons work across many types.
python
print("a" == "a")
print([1, 2] == [1, 2])
2. Ordering Comparisons¶
Ordering operators compare relative size.
python
print(3 < 5)
print(10 > 7)
print(4 <= 4)
print(8 >= 10)
Output:
text
True
True
True
False
These are especially common in loops and conditions.
3. Chained Comparisons¶
Python supports chained comparisons.
python
x = 7
print(0 < x < 10)
Output:
text
True
This is equivalent to:
python
print(0 < x and x < 10)
but is often more readable.
4. Comparing Different Types¶
Some comparisons between unlike types are allowed, while others are not.
python
print(3 == 3.0)
Output:
text
True
But ordering unrelated types may fail.
```python
"3" < 4 # TypeError¶
```
Python does not impose arbitrary ordering across unrelated types.
5. Identity vs Equality¶
Python distinguishes equality from identity.
```python a = [1, 2] b = [1, 2]
print(a == b) print(a is b) ```
Output:
text
True
False
==checks whether values are equalischecks whether two names refer to the same object
This distinction is especially important with None.
6. Membership Comparisons¶
Python also provides membership tests.
| Operator | Meaning |
|---|---|
in |
value is present |
not in |
value is absent |
Example:
python
print("a" in "cat")
print(5 in [1, 2, 5])
Output:
text
True
True
7. Worked Examples¶
Example 1: password check¶
```python password = "secret"
print(password == "secret") ```
Output:
text
True
Example 2: numeric range¶
```python score = 82
if 80 <= score < 90: print("B range") ```
Example 3: membership¶
```python colors = ["red", "green", "blue"]
if "green" in colors: print("found") ```
8. Common Pitfalls¶
Using is instead of ==¶
For value comparison, use ==, not is.
Comparing unrelated types with ordering operators¶
Expressions like "10" < 20 are invalid.
9. Summary¶
Key ideas:
- comparisons produce Boolean results
- equality and ordering comparisons are fundamental to control flow
- chained comparisons improve readability
==andishave different meanings- membership tests also produce Boolean values
Comparison operators allow Python programs to reason about relationships between values.
Exercises¶
Exercise 1.
Python supports chained comparisons like 1 < x < 10. Predict the output of each expression and explain how Python evaluates them:
python
print(1 < 2 < 3)
print(1 < 2 > 0)
print(1 < 3 > 2 < 5)
print((1 < 2) < 3)
Why does the last expression produce a different result than 1 < 2 < 3? What hidden operation does Python perform when you write (1 < 2) < 3?
Solution to Exercise 1
Output:
text
True
True
True
True
Wait -- the last one requires careful analysis. 1 < 2 < 3 is a chained comparison: Python evaluates it as 1 < 2 and 2 < 3, which is True and True = True.
1 < 2 > 0 is 1 < 2 and 2 > 0 = True and True = True.
1 < 3 > 2 < 5 is 1 < 3 and 3 > 2 and 2 < 5 = True and True and True = True.
(1 < 2) < 3 is NOT a chained comparison because of the parentheses. (1 < 2) evaluates to True. Then True < 3 compares a boolean to an integer. Since bool is a subclass of int and True == 1, this becomes 1 < 3, which is True.
The difference is subtle: if we had (1 < 2) < 1, it would be True < 1, which is 1 < 1 = False. But the unchained version 1 < 2 < 1 would be 1 < 2 and 2 < 1 = True and False = False. In this particular case both happen to be False, but the mechanism differs.
Exercise 2. A programmer checks whether two lists are equal:
```python a = [1, 2, 3] b = [1, 2, 3] c = a
print(a == b) print(a is b) print(a == c) print(a is c) ```
Predict all four outputs. Then explain: if a == b is True, why would you ever need is? Give the one case where is should always be used instead of ==.
Solution to Exercise 2
Output:
text
True
False
True
True
a == b is True because both lists contain the same values in the same order -- == compares values. a is b is False because a and b are two separate list objects in memory -- is compares identity (whether they are the same object).
a == c is True (same values) and a is c is also True because c = a makes c point to the same object as a.
The one case where is should always be used: comparing to None. Write if x is None:, not if x == None:. This is because None is a singleton -- there is exactly one None object. Using is is both faster (identity check vs value comparison) and safer (a class could define __eq__ to return True when compared with None, making == unreliable).
Exercise 3.
Python allows == between different types but restricts < and >. Predict which expressions succeed and which raise errors:
python
print(3 == 3.0)
print(3 == "3")
print(True == 1)
print(True == 1.0)
print("abc" < "abd")
print([1, 2] < [1, 3])
print(1 < "2")
Why does Python allow 3 == 3.0 but forbid 1 < "2"? What design principle does this reflect?
Solution to Exercise 3
Results:
text
True # 3 == 3.0 succeeds: cross-type numeric equality
False # 3 == "3" succeeds: different types, not equal
True # True == 1 succeeds: bool is subclass of int
True # True == 1.0 succeeds: numeric promotion
True # string comparison: 'c' < 'd' lexicographically
True # list comparison: element-by-element, 2 < 3
TypeError # 1 < "2" fails: no ordering between int and str
Python allows 3 == 3.0 because equality can always safely return False for incompatible types -- if two objects are of unrelated types, they are simply "not equal." No harm done.
But 1 < "2" is forbidden because ordering between unrelated types has no meaningful interpretation. Is 1 less than "2"? There is no sensible answer. Python 2 allowed this (using arbitrary but consistent type-based ordering), and it was a major source of bugs. Python 3 explicitly rejects meaningless comparisons, following the principle: "Errors should never pass silently."