
Let us trace the journey so far:
==, !=, >, <, >=, <=) that ask a single yes/no question and produce True or False.and, or, not) to combine multiple questions into one decision. We also discovered truthiness — every value in Python is secretly True or False.But here is the problem — we can ask questions, we can combine them, we get answers (True or False). And then... nothing happens. The program still runs every single line of code regardless. age >= 18 returns True, but the program does not actually do anything different for an adult versus a minor. The answer just sits there, unused.
Think of it this way: you have built a complete security system with sensors, cameras, and alarms. The sensors detect motion. The cameras capture footage. But there is no one watching the monitors. No one deciding "intruder detected → lock the doors." The system collects information but never acts on it.
Conditionals are the person watching the monitors. They take the True or False answers from Parts 11 and 12 and make decisions — if this is true, do one thing; otherwise, do something else. This is the moment your programs stop being calculators and start thinking.
Before we write any if statement, understand what happens under the hood. When Python encounters if something:, it calls bool() on something. That is it. The result is True → run the block. False → skip the block.
This connects to Part 12's truthiness rules:
if "hello": # bool("hello") → True → runs
print("truthy")
if 0: # bool(0) → False → skipped
print("never")
if [1, 2, 3]: # bool([1,2,3]) → True (non-empty) → runs
print("has items")
Every if statement is a bool() call. That is why we covered truthiness in Part 12 before conditionals — it was not a separate topic. It was preparation for this moment. When you see if name:, you already know Python calls bool(name), checks __bool__() or __len__(), and gets True or False. No mystery. No magic. You understand the full chain.
The simplest conditional — execute a block of code only if a condition is True:
age = 20
if age >= 18:
print("You are an adult")
print("You can vote")
print("Program continues")
Output:
You are an adult
You can vote
Program continues
if condition:
# code that runs only if condition is True
# (indented by 4 spaces)
Three critical rules:
bool() on it to get True or False:{} to define blocksage = 15
if age >= 18:
print("You are an adult") # Skipped — condition is False
print("This always runs") # Not indented — outside the if block
Output:
This always runs
In Python, indentation defines what belongs inside the if block. Unlike other languages that use {}, Python uses whitespace:
if True:
print("Inside the block")
print("Still inside")
print("Outside the block")
If you mix tabs and spaces, or indent inconsistently, Python raises an IndentationError. Use 4 spaces per level — this is the Python standard.
Why indentation and not curly braces? Most languages — C, Java, JavaScript — use {} to define blocks. Guido van Rossum chose indentation because developers already indent their code for readability anyway. Python just makes it a rule instead of a suggestion. The result: Python code looks clean by force. You cannot write messy Python — the language will not let you.
When you need exactly two paths — do this OR do that:
age = 15
if age >= 18:
print("You are an adult")
else:
print("You are a minor")
One of the two blocks always runs. There is no scenario where neither executes.
if condition:
# path A (when True)
else:
# path B (when False)
Important: else is always optional. A standalone if without else is perfectly valid — it means "do this if true, otherwise do nothing and move on." You add else only when you need a specific action for the False case.
When you need more than two paths:
score = 85
if score >= 90:
print("Grade: A")
elif score >= 80:
print("Grade: B")
elif score >= 70:
print("Grade: C")
elif score >= 60:
print("Grade: D")
else:
print("Grade: F")
Output: Grade: B
Note: Both elif and else are optional. You can have if alone, if-else, if-elif, or if-elif-else. You build only the paths your logic needs.
Python checks conditions from top to bottom. The moment it finds a True condition, it runs that block and skips all the rest.
For score = 85:
score >= 90 → 85 >= 90 → False → skipscore >= 80 → 85 >= 80 → True → run this block, skip everything belowThis is why the order matters. If you write the conditions in the wrong order, you get wrong results:
# WRONG ORDER:
score = 95
if score >= 60:
print("Grade: D") # This runs! 95 >= 60 is True
elif score >= 90:
print("Grade: A") # Never reached
score = 95
# Multiple if — checks ALL conditions independently
if score >= 90:
print("Grade: A") # Runs
if score >= 80:
print("Grade: B") # Also runs! (95 >= 80)
if score >= 70:
print("Grade: C") # Also runs! (95 >= 70)
# elif — stops at the first True
if score >= 90:
print("Grade: A") # Runs
elif score >= 80:
print("Grade: B") # Skipped — already found a match
elif score >= 70:
print("Grade: C") # Skipped
Multiple if statements are independent checks. elif is one chain where only the first match executes.
Order is not just about getting the right answer. In production code, condition order affects performance.
Consider a login system that checks three things:
# Non-optimal order:
if account_not_banned and password_correct and user_exists:
print("Login successful")
This works — it gives the correct answer. But think about what happens in production: 90% of failed logins are because the user typed the wrong password. Only 1% are banned accounts. Yet this code checks ban status first for every single request — wasting time on a check that almost never fails.
# Optimal order — cheapest and most likely to fail check first:
if user_exists and password_correct and account_not_banned:
print("Login successful")
Python's short-circuit evaluation (from Part 12) means: if user_exists is False, it never checks the other two. If password_correct is False, it never checks ban status. The most common failure (password_correct) is checked early, so most requests exit fast.
Professional developers think about this when writing APIs that handle thousands of requests per second — every unnecessary check adds up.
Here is something most developers never learn — even in computer science classes.
When your CPU reaches an if statement, it does not wait for the condition to be evaluated. It guesses which path will be taken and starts executing that path before it knows the answer. This is called branch prediction.
Modern CPUs (Intel, AMD, Apple Silicon) have sophisticated prediction algorithms. They look at patterns: "The last 100 times this condition was checked, it was True 95 times — so I will guess True again."
This is why predictable conditions are faster than random ones. If your if statement follows a pattern (many Trues in a row, then many Falses), the CPU predicts correctly almost every time. If the condition flips randomly between True and False, the CPU guesses wrong constantly and wastes cycles.
This exact phenomenon is behind one of the most famous Stack Overflow questions of all time — "Why is processing a sorted array faster than an unsorted array?" — with 35,000+ upvotes. The answer: with sorted data, the if condition follows a pattern the CPU can predict. With unsorted data, it cannot.
Read it yourself: Why is processing a sorted array faster than an unsorted array?
You do not need to optimize for branch prediction in everyday Python code. But knowing this exists separates developers who understand the machine from those who just write code on top of it.
You can put an if inside another if:
age = 25
has_id = True
if age >= 18:
if has_id:
print("Entry allowed")
else:
print("Show ID first")
else:
print("Too young")
Each nesting level adds one more indentation. The inner if only runs if the outer if is True.
Deeply nested code is hard to read — developers call this the "arrow problem" or "pyramid of doom":
if user_exists:
if password_correct:
if account_active:
if not banned:
print("Login successful")
else:
print("Account banned")
else:
print("Account inactive")
else:
print("Wrong password")
else:
print("User not found")
You can flatten nested conditionals using and from Part 12:
# Nested version:
if age >= 18:
if has_id:
print("Entry allowed")
# Flattened version (same logic):
if age >= 18 and has_id:
print("Entry allowed")
The flattened version is cleaner and easier to read. This is one of the reasons you learned logical operators first.
For the login example:
if user_exists and password_correct and account_active and not banned:
print("Login successful")
One line, same logic, much easier to understand at a glance.
Senior developers avoid deep nesting whenever possible. Compare these approaches:
# Deeply nested — hard to read:
username = input("Username: ")
password = input("Password: ")
if username != "":
if password != "":
if username == "admin":
if password == "secret123":
print("Login successful")
else:
print("Wrong password")
else:
print("Unknown user")
else:
print("Password cannot be empty")
else:
print("Username cannot be empty")
# Flattened with elif — same logic, much easier to read:
username = input("Username: ")
password = input("Password: ")
if not username:
print("Username cannot be empty")
elif not password:
print("Password cannot be empty")
elif username != "admin":
print("Unknown user")
elif password != "secret123":
print("Wrong password")
else:
print("Login successful")
The flattened version checks failure conditions first and handles them immediately. The "happy path" (success) is at the bottom. No nesting. This is called the guard clause pattern — check for problems first, handle them, then proceed with the real logic.
When you learn functions later, this pattern becomes even more powerful with early return. For now, practice flattening nested conditionals using elif and logical operators.
You might think machine learning is some magical, complex technology far beyond what you are learning. Here is the truth:
A Decision Tree — one of the most widely used ML algorithms — is literally a tree of if-elif-else statements. Imagine a bank deciding whether to approve a loan:
if credit_score < 600:
decision = "rejected"
elif income < 30000:
decision = "rejected"
elif existing_loans > 3:
decision = "rejected"
else:
decision = "approved"
That is a Decision Tree. The ML algorithm analyzes thousands of past loan applications and figures out the best conditions and thresholds automatically — but the final output is just an if-elif-else chain. The same structure you learned in this part.
Random Forest — one of the most powerful ML models used in production at companies like Netflix and Amazon — is just hundreds of Decision Trees voting together. Each tree is an if-elif-else chain. Each tree gives an answer — approved or rejected. The majority wins.
When someone says "I built a machine learning model" — in many cases, what they built is a giant if-elif-else tree that the computer wrote by learning patterns from data. The concept you learned right now is the same concept powering ML models in production.
Read more: Decision Trees — scikit-learn | Random Forest — scikit-learn
Write a program that:
Use: input(), int(), if-elif-else, comparison operators, chained comparisons (Part 12).
Write a program that:
balance = 10000 and pin = "1234"Use: if-elif-else, guard clause pattern, truthiness, comparison operators.
You are given this deeply nested code. Rewrite it using the guard clause pattern with if-elif-else — no nesting deeper than one level:
age = int(input("Age: "))
has_ticket = input("Have ticket? (yes/no): ")
has_id = input("Have ID? (yes/no): ")
if age >= 18:
if has_ticket == "yes":
if has_id == "yes":
print("Welcome to the event!")
else:
print("ID required for entry")
else:
print("You need a ticket")
else:
print("Must be 18 or older")
Use: if-elif-else, and (Part 12), guard clause pattern.
Next: Part 14 — Professional Conditional Patterns. You can now make any decision in code. But there are cleaner, more professional ways to write these — the ternary operator, match-case, and real-world patterns that experienced developers use daily.
For vs While: The Loop Decision Every Pro Developer Must Know | Python in Kannada | Part-16
Part 16
For vs While: The Loop Decision Every Pro Developer Must Know | Python in Kannada | Part-16
Part 16