|$ curl https://forge-ai.dev/api/markdown?path=docs/python/booleans
$cat docs/python-—-booleans-&-conditionals.md
updated Recently·12 min read·published
Python — Booleans & Conditionals
◆Python◆Beginner
Introduction
Booleans represent truth values — True and False. In Python, bool is a subclass of int, and every object has an inherent truth value used in conditions.
Boolean Literals
booleans.py
Python
| 1 | # Only two boolean values |
| 2 | is_ready = True |
| 3 | is_done = False |
| 4 | |
| 5 | # bool is a subclass of int |
| 6 | print(True == 1) # → True |
| 7 | print(False == 0) # → True |
| 8 | print(True + True) # → 2 |
| 9 | print(True * 10) # → 10 |
| 10 | |
| 11 | # bool() constructor |
| 12 | print(bool(1)) # → True |
| 13 | print(bool(0)) # → False |
| 14 | print(bool("hi")) # → True |
| 15 | print(bool("")) # → False |
Truthiness
Every Python object is truthy or falsy. Falsy values evaluate to False in boolean contexts like if statements.
| Falsy Values | Reason |
|---|---|
| False | Boolean false |
| None | Null value |
| 0, 0.0, 0j | Zero numeric values |
| "" | Empty string |
| [], (), | Empty collections |
| set(), range(0) | Empty set/range |
truthiness.py
Python
| 1 | # Truthiness in conditions |
| 2 | if "hello": # truthy → runs |
| 3 | if 0: # falsy → skipped |
| 4 | if []: # falsy → skipped |
| 5 | if [1, 2]: # truthy → runs |
| 6 | if None: # falsy → skipped |
| 7 | |
| 8 | # Custom objects default to truthy |
| 9 | class AlwaysTrue: |
| 10 | pass |
| 11 | |
| 12 | obj = AlwaysTrue() |
| 13 | if obj: # True by default |
| 14 | print("always truthy") |
| 15 | |
| 16 | # Override with __bool__ or __len__ |
| 17 | class MyList: |
| 18 | def __init__(self, items): |
| 19 | self.items = items |
| 20 | def __bool__(self): |
| 21 | return len(self.items) > 0 |
| 22 | def __len__(self): |
| 23 | return len(self.items) |
| 24 | |
| 25 | print(bool(MyList([]))) # → False |
| 26 | print(bool(MyList([1]))) # → True |
ℹ
info
Use if x: instead of if x is True: or if x == True:. It's more Pythonic and works for all truthy/falsy values.
Logical Operators
logical.py
Python
| 1 | # and, or, not |
| 2 | print(True and False) # → False |
| 3 | print(True or False) # → True |
| 4 | print(not True) # → False |
| 5 | |
| 6 | # Short-circuit evaluation |
| 7 | # and: stops at first falsy |
| 8 | def a(): |
| 9 | print("called a"); return False |
| 10 | def b(): |
| 11 | print("called b"); return True |
| 12 | result = a() and b() # b() never called (short-circuits) |
| 13 | |
| 14 | # or: stops at first truthy |
| 15 | result = b() or a() # a() never called |
| 16 | |
| 17 | # and/or return the last evaluated value, not bool |
| 18 | print(0 and 42) # → 0 (falsy, short-circuits) |
| 19 | print(3 and 42) # → 42 (both truthy, returns last) |
| 20 | print(0 or 42) # → 42 (falsy, evaluates second) |
| 21 | print(3 or 42) # → 3 (truthy, short-circuits) |
| 22 | |
| 23 | # Common pattern: default value |
| 24 | name = input() or "Guest" |
| 25 | # If input is empty string (falsy), defaults to "Guest" |
Comparison Operators
comparisons.py
Python
| 1 | # Equality |
| 2 | print(5 == 5) # → True |
| 3 | print(5 == "5") # → False (different types) |
| 4 | print(5 != 3) # → True |
| 5 | |
| 6 | # Ordering |
| 7 | print(5 < 10) # → True |
| 8 | print(5 <= 5) # → True |
| 9 | print(5 > 10) # → False |
| 10 | |
| 11 | # Chained comparisons (unique to Python!) |
| 12 | x = 5 |
| 13 | print(1 < x < 10) # → True |
| 14 | print(1 < x < 4) # → False |
| 15 | print(1 < x <= 5) # → True |
| 16 | # Equivalent to: 1 < x and x < 10 |
| 17 | |
| 18 | # Identity: is vs == |
| 19 | a = [1, 2, 3] |
| 20 | b = [1, 2, 3] |
| 21 | c = a |
| 22 | print(a == b) # → True (same value) |
| 23 | print(a is b) # → False (different objects) |
| 24 | print(a is c) # → True (same object) |
| 25 | |
| 26 | # None checks — ALWAYS use 'is' |
| 27 | x = None |
| 28 | if x is None: # correct |
| 29 | if x is not None: # correct |
| 30 | if x == None: # technically works but avoid |
| 31 | |
| 32 | # Membership |
| 33 | print(2 in [1, 2, 3]) # → True |
| 34 | print("x" in "hello") # → False |
Conditional Expressions
ternary.py
Python
| 1 | # Ternary (conditional expression) |
| 2 | age = 20 |
| 3 | status = "adult" if age >= 18 else "minor" |
| 4 | |
| 5 | # Chained ternary (avoid for complex cases) |
| 6 | score = 85 |
| 7 | grade = "A" if score >= 90 else "B" if score >= 80 else "C" |
| 8 | |
| 9 | # Nested ternary — less readable, use if/elif |
| 10 | grade = ( |
| 11 | "A" if score >= 90 else |
| 12 | "B" if score >= 80 else |
| 13 | "C" if score >= 70 else |
| 14 | "F" |
| 15 | ) |
| 16 | |
| 17 | # In comprehensions: ternary in expression (not filter) |
| 18 | values = ["even" if x % 2 == 0 else "odd" for x in range(5)] |
| 19 | # → ["even", "odd", "even", "odd", "even"] |
all() and any()
all_any.py
Python
| 1 | # all() — True if ALL items are truthy |
| 2 | print(all([True, True, True])) # → True |
| 3 | print(all([True, False, True])) # → False |
| 4 | print(all([])) # → True (vacuous truth) |
| 5 | |
| 6 | # any() — True if ANY item is truthy |
| 7 | print(any([False, False, True])) # → True |
| 8 | print(any([False, False, False])) # → False |
| 9 | print(any([])) # → False |
| 10 | |
| 11 | # Practical examples |
| 12 | nums = [1, 2, 3, 4, 5] |
| 13 | print(all(x > 0 for x in nums)) # → True (all positive) |
| 14 | print(any(x > 3 for x in nums)) # → True (4 and 5) |
| 15 | |
| 16 | # Validation |
| 17 | users = [ |
| 18 | {"name": "Alice", "active": True}, |
| 19 | {"name": "Bob", "active": False}, |
| 20 | ] |
| 21 | print(all(u["active"] for u in users)) # → False |
Common Pitfalls
pitfalls.py
Python
| 1 | # 1. Chaining vs 'and' chaining |
| 2 | # Python's chained comparisons are NOT like 'and' |
| 3 | def check(x): |
| 4 | return 0 < x < 10 |
| 5 | |
| 6 | def check_and(x): |
| 7 | return 0 < x and x < 10 |
| 8 | |
| 9 | # These seem equivalent but chained evaluates x only once |
| 10 | # Useful when x is an expression |
| 11 | |
| 12 | # 2. 'is' vs '==' with integers (small integer caching) |
| 13 | a = 256 |
| 14 | b = 256 |
| 15 | print(a is b) # → True (CPython caches -5 to 256) |
| 16 | |
| 17 | a = 257 |
| 18 | b = 257 |
| 19 | print(a is b) # → False (different objects!) |
| 20 | # Always use == for value comparison |
| 21 | |
| 22 | # 3. Comparing different types |
| 23 | print(1 < "2") # TypeError in Python 3 |
| 24 | |
| 25 | # 4. == vs is for None/True/False |
| 26 | x = True |
| 27 | if x is True: # fine for singletons |
| 28 | if x == True: # works but less idiomatic |
| 29 | |
| 30 | # 5. Floating point equality |
| 31 | print(0.1 + 0.2 == 0.3) # → False! |
| 32 | # Use math.isclose instead |
| 33 | import math |
| 34 | print(math.isclose(0.1 + 0.2, 0.3)) # → True |
$Blueprint — Engineering Documentation·Section ID: PYTHON-BOOL·Revision: 1.0