andBoth sides must be truthy.
can_checkout = has_items and payment_readyLearn with diagrams, code, systems and practical examples.
Represent yes/no conditions and combine them safely.
Programs need to decide whether a user is allowed, a value is valid, or a task is complete.
Boolean values are True and False. Comparisons create booleans, while and, or, and not combine or invert conditions.
Run this example first. Do not change several things at once; confirm the basic behavior, then experiment.
age = 21
has_ticket = True
can_enter = age >= 18 and has_ticket
print(can_enter) Boolean values are True and False. Comparisons create booleans, while and, or, and not combine or invert conditions.
TrueThe example is intentionally small. Focus on the chapter’s main idea before adding extra syntax or framework code.
Writing complex conditions without parentheses or intermediate variable names.
Break large conditions into named booleans so each rule is understandable.
These are deliberately small. If you can complete them without copying the example, you are ready to continue.
Prepared deep chapter · Core Python
A program often needs to answer a small yes-or-no question before it can decide what to do next. Is a password long enough? Is an order total above a discount threshold? Is a required field present? Did a search find the value we need? Python represents those answers with the Boolean values True and False.
The goal of this chapter is not to memorize every comparison symbol. It is to build a reliable decision habit: state the fact you want to test, write the smallest clear comparison, combine rules only when needed, then verify the result.
if statement.Python's Boolean type is called bool. It has two values: True and False. Notice the capital letters. Writing true or false does not create Python Boolean values.
is_member = True
is_blocked = False
print(is_member)
print(is_blocked)
print(type(is_member).__name__) True
False
boolYou can write Boolean values directly, but most useful Booleans come from checking facts. A comparison such as age >= 18 asks a question and produces True or False.
Suppose an order gets free shipping at 50 dollars. The rule is easier to understand when the comparison looks like the sentence: “Is the order total at least 50?”
order_total = 72
has_free_shipping = order_total >= 50
print(has_free_shipping) True| Operator | Question | Example |
|---|---|---|
== | Are the values equal? | status == "paid" |
!= | Are the values different? | role != "guest" |
< | Is the left value smaller? | temperature < 0 |
<= | Is the left value smaller or equal? | attempts <= 3 |
> | Is the left value larger? | stock > 0 |
>= | Is the left value larger or equal? | age >= 18 |
= assigns a value. == compares two values. If you are asking “are these equal?”, use ==.
Python lets you write a range check in the same order you might say it:
temperature = 21
comfortable = 18 <= temperature <= 24
print(comfortable) TrueThe middle value is evaluated once. This is usually clearer than writing the same value twice in a longer and expression.
Python can treat many values as true or false in a condition. Empty strings, empty lists, empty dictionaries, zero, None, and False are common falsey values. Many non-empty values are truthy.
coupon_code = ""
items = ["book", "pen"]
print(bool(coupon_code))
print(bool(items)) False
TrueUse truthiness when the meaning really is “empty versus not empty.” If your domain distinguishes zero, missing, blank, and invalid values, write the more precise check instead of hiding those states behind one truthy/falsy test.
and, or, and notOnce each individual fact is clear, Boolean operators let you combine them.
andBoth sides must be truthy.
can_checkout = has_items and payment_readyorAt least one side must be truthy.
can_edit = is_owner or is_adminnotInvert a truth value.
should_retry = not request_succeededWhen a condition becomes long, name the individual rules first. Good names make the decision explain itself.
age = 21
has_ticket = True
is_banned = False
is_adult = age >= 18
can_enter = is_adult and has_ticket and not is_banned
print(can_enter) TruePython evaluates and and or from left to right and can stop as soon as the result is determined. This is called short-circuiting.
user = None
can_read_name = user is not None and user.name != ""
print(can_read_name) FalseBecause user is not None is false, Python does not evaluate the second part. That prevents an attribute lookup on None. Short-circuiting is useful, but it should not become a trick for hiding confusing side effects inside conditions.
is, ==, and in answer different questionsThese operators can look similar because they all produce Boolean-like results, but they ask different questions.
==Use it when you care whether two values compare equal.
status == "paid"isUse it when you care whether two references point to the very same object. The common beginner use is value is None.
result is NoneinUse it to ask whether a value belongs to a container.
role in {"admin", "editor"}Do not use is as a replacement for == when comparing normal strings or numbers. Identity and equality are different questions.
A checkout can continue only when the cart has items, the account is active, the delivery country is supported, and the order is below a manual-review threshold.
items = ["book", "pen"]
account_active = True
country = "US"
order_total = 86
supported_countries = {"US", "CA", "GB"}
has_items = bool(items)
country_supported = country in supported_countries
within_limit = order_total < 500
can_checkout = (
has_items
and account_active
and country_supported
and within_limit
)
print(can_checkout) TrueEach named Boolean answers one question. That makes the final rule readable and gives you useful checkpoints when debugging.
= and ==Assignment changes a binding; equality asks a question.
is for value equalityUse == for ordinary value comparison; reserve identity tests for identity questions such as is None.
0, "", and None can all be falsey, but they may mean different things in your domain.
Break important rules into named Booleans so readers can inspect them independently.
Put a guard such as value is not None before an access that depends on it.
0 <= temperature < 10 for temperature = -2, 0, and 7.{"admin", "editor"} and the account is not suspended.value is None with value == None. Use the Python style you would choose in real code and explain why.and/or condition into three named Boolean variables.True and False are the two Boolean values.and, or, and not combine or invert rules, and and/or short-circuit.== checks value equality, is checks identity, and in checks membership.Next chapter: If, Elif, and Else — where Boolean results decide which code actually runs.
Prediction lab · prepared for the next Python chapter
Boolean code becomes easier when you stop reading it as one long sentence and instead inspect one fact at a time. For each trace below, predict the result first, then read the explanation. The goal is not speed. The goal is to build a repeatable debugging habit you can use when a condition looks correct but behaves differently from what you expected.
coupon = ""
customer_id = None
has_coupon = bool(coupon)
has_customer = customer_id is not None
print(has_coupon)
print(has_customer) Expected output: False and then False.
The first check asks whether the string is empty. The second asks whether a value exists at all. Both happen to be false here, but they describe different states. If your program needs to distinguish “blank text” from “missing value,” one truthiness check is too vague.
profile = None
can_read_name = (
profile is not None
and profile.name != ""
)
print(can_read_name) Expected output: False.
Python evaluates the left side of and first. Once profile is not None is false, the complete expression cannot become true, so Python does not evaluate profile.name. This is useful because the second check only makes sense when a profile object exists.
Common mistake: reversing those two checks would try to read profile.name before proving that profile is an object.
role = "editor"
allowed_roles = {"admin", "editor"}
is_editor = role == "editor"
can_manage = role in allowed_roles
print(is_editor)
print(can_manage) Expected output: True and then True.
The equality check asks whether the role is exactly one value. The membership check asks whether that value belongs to a set of approved choices. When requirements grow from one accepted value to several, membership often describes the business rule more clearly.
Deeper detail · Python-specific behavior
and and or return operands, not always True or FalsePython first tests truthiness, but the value returned by and or or can be one of the original operands. This is useful for compact fallback patterns, but it can surprise beginners who expect every Boolean-looking expression to produce the bool type.
or returns the first truthy operand display_name = "" or "Guest"
print(display_name)
print(type(display_name).__name__) Expected output: Guest, then str.
The empty string is falsey, so Python evaluates and returns the second operand. The result is a string, not the Boolean value True.
and returns the first falsey operand, otherwise the last operand profile = {"name": "Asha"}
name = profile and profile["name"]
print(name)
profile = {}
name = profile and profile["name"]
print(name) Expected output: Asha, then {}.
With a non-empty dictionary, Python evaluates the second operand and returns the name. With an empty dictionary, it stops immediately and returns that empty dictionary.
If your intent is “I need an actual Boolean,” use a comparison or wrap the expression in bool(...). Use operand-returning and/or patterns only when returning a real value is intentional and clear to the next reader.
Quick reference · bookmark-worthy decision aid
When a Boolean condition gets confusing, start with the sentence you are trying to answer. The table below maps common intentions to a clear Python pattern and the mistake most likely to blur the meaning.
| Question you mean | Clear Python pattern | Watch for |
|---|---|---|
| Is the value missing? | value is None | Do not replace this with not value if 0 or "" are valid values. |
| Is a collection empty? | not items | Use this only when empty/non-empty is really the business rule. |
| Does this value equal one expected value? | status == "paid" | is asks about object identity, not normal value equality. |
| Is this value one of several allowed choices? | role in allowed_roles | A long chain of or comparisons is harder to extend and review. |
| Is a number inside a range? | 18 <= age <= 64 | Check whether the endpoints should be included before choosing < or <=. |
| Can I safely run a dependent check? | profile is not None and profile.name != "" | Put the guard first so short-circuiting can protect the dependent access. |
Use this as a debugging worksheet: say the question in plain language, pick the matching pattern, then print or inspect the smaller facts before combining them.
coupon to "SAVE10" and predict which trace value changes. Then change customer_id to 0 and explain why customer_id is not None becomes true even though bool(0) would be false."viewer" to allowed_roles, set role = "viewer", and predict why is_editor becomes false while can_manage can remain true.display_name = "" or "Guest" to display_name = "Mira" or "Guest". Predict both the value and its type, then explain why or did not return True.When a Boolean expression surprises you, write down the value of each named fact before combining them. A clear sequence of small checks is easier to verify than a clever one-line condition.