Previous | Tutorial index | Next
and / orUse logical operators (and, or, not) to check multiple conditions inside a single if statement, enabling complex decision-making with minimal code.
In Tutorials 1–4, we used comparison operators (>, <, ==, etc.) to create simple conditions like age > 18. But real-world decisions are rarely that simple.
age >= 16 AND has_license == True.weather == "rainy" OR forecast == "stormy".Logical operators (and, or, not) allow us to combine multiple boolean expressions into a single, compound condition that evaluates to a single True or False.
| Operator | Name | What it does | True Example | False Example |
|---|---|---|---|---|
and |
Logical AND | Returns True only if both sides are True. |
(5 > 3) and (10 > 7) → True |
(5 > 3) and (10 < 7) → False |
or |
Logical OR | Returns True if at least one side is True. |
(5 > 3) or (10 < 7) → True |
(5 < 3) or (10 < 7) → False |
not |
Logical NOT | Reverses the boolean value. | not (5 > 3) → False |
not (5 < 3) → True |
Python is lazy when evaluating compound conditions—it stops as soon as the final result is determined. This is called short-circuiting.
and short-circuits at the first False: Since False and anything is always False, Python doesn't bother checking the second condition.
x = 0
if x != 0 and 10 / x > 5: # The division NEVER happens! Safe!
print("Safe")
or short-circuits at the first True: Since True or anything is always True, Python doesn't check the second condition.
name = "admin"
if name == "admin" or name == "superuser": # Stops at "admin" (True), never checks "superuser"
print("Access granted")
not Operatornot simply flips a boolean. It's often used to check for "absence" or "failure".
if not logged_in: (Runs if logged_in is False)if not (age >= 18): (Runs if age is not 18 or older)Python's logical operators don't just return True or False—they return the actual value of the last evaluated operand!
0 and 10 returns 0 (because 0 is falsy).5 and 10 returns 10 (the last value checked).0 or 5 returns 5 (the first truthy value).Beginner note: While this is a powerful feature, for this course, we recommend writing conditions that explicitly return
True/Falsefor clarity.
if condition1 and condition2:
# Runs ONLY if BOTH condition1 AND condition2 are True
if condition1 or condition2:
# Runs if AT LEAST ONE (condition1 or condition2) is True
if not condition1:
# Runs if condition1 is False
Just like math has rules (multiplication before addition), Python evaluates logical operators in a specific order:
>, <, ==, etc.) happen first.not comes next.and comes after not.or comes last (lowest priority).Crucial Rule: If you mix and and or in the same statement, and is evaluated before or.
# Without parentheses (confusing)
if age >= 18 and age <= 65 or age == 0:
# This is evaluated as: (age >= 18 and age <= 65) or age == 0
# With parentheses (CLEAR and SAFE)
if (age >= 18 and age <= 65) or (age == 0):
# This is evaluated exactly as intended.
Golden Rule: Always use parentheses
()to make your intentions crystal clear. It prevents bugs and makes your code easier to read.
and)Python allows a unique shorthand for checking if a value is within a range:
if 18 <= age <= 65: is exactly the same as if age >= 18 and age <= 65:.if 0 < x < 10: checks if x is between 0 and 10 exclusively.Objective: Grant access only if the username is "admin" AND the password is "secret".
username = input("Enter username: ")
password = input("Enter password: ")
if username == "admin" and password == "secret":
print("Access Granted. Welcome, admin!")
else:
print("Access Denied. Invalid credentials.")
admin / secret → "Access Granted".admin / wrong → "Access Denied" (First is True, second is False → overall False).user / secret → "Access Denied" (First is False → Python short-circuits and doesn't even check the password!).day = input("Enter day: ").lower()
is_holiday = input("Is it a holiday? (yes/no): ").lower() == "yes"
if day == "saturday" or day == "sunday" or is_holiday:
print("You get to relax today!")
else:
print("It's a workday.")
or allows multiple "paths" to True. If it's Saturday, OR Sunday, OR a holiday—any one makes it True.age = int(input("Enter your age: "))
if (age >= 18 and age <= 65):
print("You are of working age.")
elif (age >= 0 and age < 18):
print("You are a minor.")
else:
print("Invalid age (or retired/senior).") # Catches > 65 and negatives
Better version with Python chaining:
if 18 <= age <= 65:
print("Working age.")
A student gets a scholarship if they have a GPA > 3.5 AND (they are an athlete OR they volunteer > 50 hours).
gpa = float(input("Enter GPA: "))
athlete = input("Are you an athlete? (yes/no): ").lower() == "yes"
volunteer_hours = int(input("Enter volunteer hours: "))
if gpa > 3.5 and (athlete or volunteer_hours > 50):
print("Congratulations! You qualify for the scholarship.")
else:
print("Sorry, you do not qualify.")
(athlete or volunteer_hours > 50). Without them, and binds tighter than or, changing the logic entirely!not)user_input = input("Enter your name: ")
if not user_input: # Equivalent to: if user_input == ""
print("You didn't type anything!")
else:
print(f"Hello, {user_input}!")
The "String OR" Trap (The #1 Beginner Mistake)
if city == "New York" or "Los Angeles":if (city == "New York") or ("Los Angeles"):. Since "Los Angeles" is a non-empty string, it is truthy, so the condition is always True!if city == "New York" or city == "Los Angeles":Forgetting Parentheses when Mixing and / or
if age > 18 and country == "USA" or country == "Canada" (Reads as (age > 18 and country == "USA") or country == "Canada", which could let a 10-year-old from Canada through!).if age > 18 and (country == "USA" or country == "Canada"):Misunderstanding Short-Circuiting in Assignments
x = 10 or some_function() → some_function() is never called because 10 is truthy. This is often unintended.Confusing and / or with Everyday English
if tea or coffee is True if either exists (or both). Python's or is inclusive, not exclusive.Overcomplicating with not
if not age < 18: is just a confusing way to write if age >= 18:. Avoid double negatives for readability.Comparing to True or False Redundantly
if is_raining == True:if is_raining: (Since is_raining is already a boolean).if is_raining == False: → Better: if not is_raining:Q1: Which logical operator requires both conditions to be True?
orandnotxorQ2: In if x != 0 and 10/x > 5, the division 10/x is always executed.
Q3: What is the output?
age = 25
country = "Canada"
if age >= 18 and country == "USA" or country == "Canada":
print("Eligible")
else:
print("Not eligible")
Q4: To check if a variable score is between 50 and 100 (inclusive), the Pythonic way is if 50 <= score <= 100:, which is equivalent to if score >= 50 _____ score <= 100:. Fill in the blank.
andornotelseQ5: What is the result of not (5 > 3)?
TrueFalse5ErrorExercise 1: Loan Eligibility
Income > $30,000 AND credit score ≥ 700 → "Approved", else "Denied".
income = float(input("Income: "))
credit = int(input("Credit score: "))
if income > 30000 and credit >= 700:
print("Loan Approved")
else:
print("Loan Denied")
Exercise 2: Vowel Check
Ask for a letter. Print "Vowel" if it is one of aeiou (case‑insensitive), otherwise "Consonant".
ch = input("Enter a letter: ").lower()
if ch == 'a' or ch == 'e' or ch == 'i' or ch == 'o' or ch == 'u':
print("Vowel")
else:
print("Consonant")
Exercise 3: Free Shipping
Spend > $50 OR premium member → "Free shipping", else "Shipping cost applies".
amount = float(input("Total amount: "))
premium = input("Premium member? (yes/no): ").lower() == "yes"
if amount > 50 or premium:
print("Free shipping")
else:
print("Shipping cost applies")
Exercise 4: Leap Year (full logic)
Leap if divisible by 400, or divisible by 4 and not by 100.
year = int(input("Year: "))
if (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0):
print("Leap year")
else:
print("Not a leap year")
Exercise 5: The Safe Division Guard
Ask for two numbers, a and b. Using and in a single if statement, check if b is not zero AND a is positive. If so, print a / b. Otherwise, print "Cannot compute."
a = float(input("Enter first number (a): "))
b = float(input("Enter second number (b): "))
if b != 0 and a > 0:
print(a / b)
else:
print("Cannot compute.")
Explanation:
b != 0 and a > 0 ensures that:
b is not zero (preventing division by zero).a is positive (restricting computation to positive numerators).True, the division is performed and printed.b == 0 or a <= 0), the else block runs and prints "Cannot compute.".b == 0, Python never evaluates a > 0 because the and already knows the result is False – but that's fine because we want to avoid division anyway.1. Why does if country == "USA" or "Canada": always evaluate to True? How do you fix it?
2. What is short‑circuit evaluation? Give an example where it prevents a runtime error.
3. What is operator precedence and why is it important when combining and, or, and not?
4. Explain the difference between and and or with real‑life examples. How would you use not to invert a condition? Give at least two examples of each.
Write down the exact output or error for each snippet.
Snippet 1:
x = 10
if x > 5 and x < 15:
print("In range")
else:
print("Out of range")
In range
Explanation: The condition x > 5 and x < 15 checks if x is between 5 and 15 (exclusive). 10 > 5 is True and 10 < 15 is True. Since both conditions are True, the overall and evaluates to True, and the if block runs.
Snippet 2:
temperature = 30
is_sunny = True
if temperature > 25 or is_sunny:
print("Good weather")
else:
print("Bad weather")
Good weather
Explanation: The condition temperature > 25 or is_sunny checks if at least one is True. 30 > 25 is True, so the or condition is satisfied immediately (short‑circuiting occurs). The if block runs and prints "Good weather". Even though the second part isn't evaluated, the result is already known.
Snippet 3 (Tricky):
country = "Mexico"
if country == "USA" or "Canada":
print("North America")
else:
print("Other")
North America
Explanation: This is the classic string or trap! Due to operator precedence, the expression is evaluated as (country == "USA") or ("Canada"). Since "Canada" is a non‑empty string, it is truthy. So the condition becomes False or True, which is True, regardless of the value of country. Therefore, the if block always runs.
Corrected version would be: if country == "USA" or country == "Canada":
Snippet 4:
logged_in = False
if not logged_in:
print("Please log in.")
else:
print("Welcome!")
Please log in.
Explanation: The not operator reverses the Boolean value. logged_in is False, so not False becomes True. The if block runs and prints "Please log in.".
Snippet 5 (Short-circuit):
x = 5
y = 0
if x > 0 or y > 0:
print("A")
if x == 5 and y / 0 > 0: # Careful!
print("B")
A
Error: ZeroDivisionError - division by zero
Explanation:
if statement: x > 0 or y > 0 evaluates 5 > 0 as True. Because or short‑circuits, it doesn't even check y > 0. So it prints "A" safely.if statement: x == 5 and y / 0 > 0. The first part x == 5 is True. For and, both parts must be evaluated (since the first is True, Python must check the second). It then evaluates y / 0 > 0, which attempts division by zero and crashes the program with a ZeroDivisionError.Key takeaway: and does NOT short‑circuit when the first part is True – it must evaluate the second part.
Identify the error(s) in each code block. Explain why it's wrong and write the corrected version.
Buggy Code 1:
age = 22
has_license = False
if age >= 18 and has_license == True:
print("Can drive")
else:
print("Cannot drive")
# Wait, this actually works, but there is a stylistic error. Can you make it more Pythonic?
Stylistic Issue: Comparing a Boolean variable directly to True or False is redundant and considered un‑Pythonic.
Why it works: The code runs correctly because has_license == True evaluates to False (since has_license is False), so the condition becomes age >= 18 and False, which is False. The else block prints "Cannot drive".
More Pythonic Version:
age = 22
has_license = False
if age >= 18 and has_license:
print("Can drive")
else:
print("Cannot drive")
Here, has_license is already a Boolean, so we use it directly.
Buggy Code 2 (Logical Error):
fruit = "Apple"
if fruit == "Apple" or "Orange":
print("It's a common fruit.")
else:
print("It's exotic.")
# This always prints "It's a common fruit." even if fruit is "Banana". Fix it!
Error: This is the string or trap. The expression fruit == "Apple" or "Orange" is parsed as (fruit == "Apple") or ("Orange"). Since "Orange" is a non‑empty string, it is truthy, so the condition is always True.
Corrected Code:
fruit = "Apple"
if fruit == "Apple" or fruit == "Orange":
print("It's a common fruit.")
else:
print("It's exotic.")
Alternative (using in):
if fruit in ["Apple", "Orange"]:
print("It's a common fruit.")
else:
print("It's exotic.")
Buggy Code 3 (Parentheses needed):
age = 20
student = True
if age > 18 and student or age < 12:
discount = 0.2
else:
discount = 0.0
print(discount)
# The goal: Give discount if (age > 18 AND student) OR age < 12.
# Is the current code correct? Test with age=20, student=True (works). Test with age=10, student=False (should give discount, but current logic? age>18 False, student False, age<12 True -> Actually, it works due to and/or precedence, but it's risky. Let's rewrite it clearly with parentheses).
Issue: The code technically works due to Python's operator precedence (and has higher precedence than or), so the condition is evaluated as (age > 18 and student) or age < 12. For the test cases:
age=20, student=True: (True and True) or False → True or False → True (discount = 0.2)age=10, student=False: (False and False) or True → False or True → True (discount = 0.2)Why it's risky: The logic is not obvious to someone reading the code. It's easy to misinterpret, and future modifications might break it.
Corrected Code with explicit parentheses:
age = 20
student = True
if (age > 18 and student) or age < 12:
discount = 0.2
else:
discount = 0.0
print(discount)
The parentheses make the intention crystal clear.
Buggy Code 4:
score = 85
if 80 <= score <= 90:
print("B grade")
else:
print("Other")
# This works, but what if we want to use 'and' to be explicit? Rewrite it using 'and'!
Goal: Rewrite the Python range check using explicit and.
Corrected Code:
score = 85
if score >= 80 and score <= 90:
print("B grade")
else:
print("Other")
Explanation: Python's chained comparison 80 <= score <= 90 is just syntactic sugar for score >= 80 and score <= 90. The explicit version is often clearer for beginners.
Write a Python script for each task. Test your code with different inputs.
Task 1: The University Admissions System A university admits a student if:
"yes"/"no"). Print "Admitted" or "Not Admitted".gpa = float(input("Enter GPA: "))
sat = int(input("Enter SAT score: "))
extracurriculars = input("Outstanding extracurriculars? (yes/no): ").lower()
if gpa >= 3.0 and (sat >= 1200 or extracurriculars == "yes"):
print("Admitted")
else:
print("Not Admitted")
Task 2: The Triangle Validator
Write a program that asks for the lengths of three sides of a triangle (a, b, c). A triangle is valid if the sum of any two sides is greater than the third side. (Use and to combine three conditions: a + b > c, a + c > b, and b + c > a). Print "Valid triangle" or "Invalid triangle".
a = float(input("Enter side a: "))
b = float(input("Enter side b: "))
c = float(input("Enter side c: "))
if (a + b > c) and (a + c > b) and (b + c > a):
print("Valid triangle")
else:
print("Invalid triangle")
Task 3: The Insurance Premium Calculator A company calculates premiums based on:
age = int(input("Enter age: "))
experience = int(input("Enter driving experience (years): "))
if (18 <= age <= 25) and experience > 2:
premium = 500
elif (26 <= age <= 40) and experience > 5:
premium = 300
else:
premium = 1000
print(f"Premium: ${premium}")
Task 4: The Online Order Validator Write a program that asks the user for:
"yes"/"no")
Apply a discount of 10% ONLY IF the quantity is greater than 10 OR (the price is greater than $100 AND the user is a member).
Print the final total price.quantity = int(input("Enter quantity: "))
price = float(input("Enter price per item: "))
member = input("Are you a member? (yes/no): ").lower()
total = quantity * price
if quantity > 10 or (price > 100 and member == "yes"):
total *= 0.9 # Apply 10% discount
print(f"Discount applied! Final price: ${total:.2f}")
else:
print(f"Final price: ${total:.2f}")
Challenge Task: The Rock-Paper-Scissors Advanced Validation
Write a program that asks the user for their move ("rock", "paper", "scissors"). Use if-elif-else and logical operators to check:
"Invalid move!"."rock" or "scissors", print "You chose a non-paper move."."paper", print "You chose paper.".move = input("Enter rock, paper, or scissors: ").lower()
if not (move == "rock" or move == "paper" or move == "scissors"):
print("Invalid move!")
elif move == "rock" or move == "scissors":
print("You chose a non-paper move.")
elif move == "paper":
print("You chose paper.")
Alternative using not in (more Pythonic):
if move not in ["rock", "paper", "scissors"]:
print("Invalid move!")
elif move == "rock" or move == "scissors":
print("You chose a non-paper move.")
else: # only "paper" left
print("You chose paper.")
Before moving to the next module, ensure you can confidently answer:
# Logical Operators
# and -> BOTH must be True
# or -> AT LEAST ONE must be True
# not -> Reverses the boolean
# Syntax with Parentheses (Best Practice)
if (condition_a and condition_b) or condition_c:
# Do something
# Common Patterns:
# 1. Range Check
if 18 <= age <= 65:
print("Adult")
# 2. Multiple Accepted Values
if day in ["Saturday", "Sunday"]: # Equivalent to day == "Sat" or day == "Sun"
print("Weekend")
# 3. Safe Operation (using and)
if denominator != 0 and numerator / denominator > 5:
print("Safe")
# 4. Default value using or
name = input("Enter name: ") or "Guest"
print(name) # If user presses Enter, name becomes "Guest"
# 5. Negation
if not user_logged_in:
print("Please login.")
Key Takeaway for Tutorial 5: Logical operators are the glue that turns simple conditions into complex, real-world decision-making logic. Always remember:
and when all conditions are required.or when any condition is acceptable.() to avoid ambiguity and make your code crystal clear.or trap (if x == "A" or "B").You now possess all the tools to write dynamic, intelligent programs that can handle a vast array of user inputs and scenarios. Combine this with what you learned in Tutorials 1–4, and you're ready to tackle almost any logic problem in Python!