Conditional Statements (if / elif / else)
The if statement is your program’s decision-maker. It executes code only if a condition is True.
Basic structure:
Python
age = 18
if age >= 18:
print("You can vote!")
else:
print("Too young to vote.")
Add branches with elif (else if):
Python
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
print(f"Your grade: {grade}")
Key points:
- Conditions must evaluate to bool (or truthy/falsy—we covered this last time).
- Indentation defines the block.
- No parentheses required, but you can use them for clarity: if (age >= 18 and score > 80):.
Nested ifs are possible but can get messy—we’ll address that later.
Full example: A simple login simulator.
Python
username = input("Username: ")
password = input("Password: ")
if username == "admin":
if password == "secret":
print("Access granted!")
else:
print("Wrong password.")
else:
print("Unknown user.")
Run this interactively. Juniors: Always consider edge cases—like empty inputs.
Boolean Logic and Comparison Operators
Conditions rely on operators.
Comparison: == (equal), != (not equal), <, >, <=, >=.
Chaining: a < b <= c (like math).
Logical: and, or, not.
Python
temperature = 25
is_sunny = True
if 20 <= temperature <= 30 and is_sunny:
print("Perfect weather!")
elif temperature < 10 or not is_sunny:
print("Stay indoors.")
Operator precedence: Comparisons before not, then and, then or. Use parentheses to clarify.
Membership and identity:
- in / not in: Check if item in sequence.
- is / is not: Identity check (same object—remember None and singletons).
Python
fruits = ["apple", "banana"]
if "apple" in fruits:
print("Healthy choice!")
value = None
if value is None:
print("No value set.")
Full example: Validating user input.
Python
email = input("Enter email: ")
if "@" in email and "." in email:
if email.endswith(".com") or email.endswith(".org"):
print("Valid email.")
else:
print("Unsupported domain.")
else:
print("Invalid format.")
Middle devs: For complex logic, consider truth tables or refactor into functions.
for Loops vs while Loops
Loops repeat code. Choose based on need.
for loops: Ideal for iterating over sequences (lists, strings, ranges).
Python
for i in range(5): # 0 to 4
print(i)
# Over list
names = ["Alice", "Bob", "Charlie"]
for name in names:
print(f"Hello, {name}")
while loops: Run until condition False. Great for unknown iterations.
Python
count = 0
while count < 5:
print(count)
count += 1
Infinite loops: while True:—break out with conditions.
Comparison:
- Use for when you know the sequence or count.
- Use while for condition-based (e.g., waiting for input).
Full example: Guessing game.
Python
import random
secret = random.randint(1, 10)
guess = 0
while guess != secret:
guess = int(input("Guess a number 1-10: "))
if guess < secret:
print("Too low!")
elif guess > secret:
print("Too high!")
else:
print("Correct!")
print("Game over.")
This uses while naturally since guesses vary.
break, continue, and pass – When to Use Them
Control loop flow precisely.
- break: Exit loop immediately.
- continue: Skip to next iteration.
- pass: Do nothing (placeholder).
Python
for num in range(10):
if num == 5:
continue # Skip 5
if num > 8:
break # Stop at 9+
print(num)
# Prints 0-4, 6-8
pass example:
Python
for i in range(5):
if i % 2 == 0:
pass # TODO: handle even
else:
print("Odd:", i)
Full example: Prime search with break.
Python
def find_prime(start=2):
num = start
while True:
is_prime = True
for i in range(2, int(num**0.5) + 1):
if num % i == 0:
is_prime = False
break # No need to check further
if is_prime:
return num
num += 1
print("Next prime after 10:", find_prime(11))
Juniors: Use sparingly—overuse leads to spaghetti code.
Looping Patterns Every Developer Should Know
Common idioms:
- Enumerate: Index + item.
Python
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits, start=1):
print(f"{index}: {fruit}")
- Zip: Parallel iteration.
Python
names = ["Alice", "Bob"]
scores = [95, 88]
for name, score in zip(names, scores):
print(f"{name}: {score}")
- List comprehensions: Concise loops.
Python
squares = [x**2 for x in range(10) if x % 2 == 0]
print(squares) # [0, 4, 16, 36, 64]
- Dictionary comprehensions.
Python
word_lengths = {word: len(word) for word in ["python", "is", "fun"]}
print(word_lengths)
Full example: Processing data.
Python
transactions = [("deposit", 100), ("withdraw", 50), ("deposit", 200)]
balance = 0
for action, amount in transactions:
if action == "deposit":
balance += amount
elif action == "withdraw":
balance -= amount
print("Final balance:", balance)
Middle devs: Comprehensions are Pythonic but don’t nest deeply—readability first.
Avoiding Deep Nesting and Spaghetti Code
Deep nesting (if inside loop inside if) hurts readability.
Solutions:
- Early returns/continues.
- Guard clauses.
- Refactor to functions.
Bad:
Python
if condition1:
if condition2:
for item in items:
if item.valid:
# do work
Better:
Python
if not condition1 or not condition2:
return # or continue
for item in items:
if not item.valid:
continue
# do work
Use any() / all() for conditions.
Python
numbers = [1, 2, 3, 4]
if all(n >for n in numbers):
print("All positive")
Flatten with comprehensions or loops.
Full example: Refactored validator.
Python
def validate_user(user):
if not user.get("name"):
return "Missing name"
if not user.get("email") or "@" not in user["email"]:
return "Invalid email"
if user["age"] < 18:
return "Too young"
return "Valid"
user = {"name": "Bob", "email": "bob@example.com", "age": 20}
print(validate_user(user))
Early returns keep main logic flat.
Performance Considerations in Loops
Loops can be bottlenecks.
Tips:
- List comprehensions often faster than for-loops with append.
- Avoid work inside loops (e.g., repeated calculations).
- Use built-ins: sum(), max(), etc.
Example timing (results vary, but comprehensions win):
Python
import timeit
nums = list(range(10000))
# Comprehension
time_comp = timeit.timeit('[x*2 for x in nums]', globals=globals(), number=1000)
# For loop
time_loop = timeit.timeit('result = []\nfor x in nums:\n result.append(x*2)', globals=globals(), number=1000)
print(f"Comprehension: {time_comp:.4f}s")
print(f"For loop: {time_loop:.4f}s")
Use generators for memory: (x*2 for x in nums).
For heavy loops, consider numba or profiling with cProfile.
Python
import cProfile
def slow_function():
total = 0
for i in range(1000000):
total += i ** 2
return total
cProfile.run('slow_function()')
Identify hotspots and optimize.
Real-World Examples and Exercises
Tie it together: Build a CLI todo list.
Python
todos = []
while True:
print("\n1. Add 2. List 3. Complete 4. Quit")
choice = input("Choose: ")
if choice == "1":
task = input("Task: ")
todos.append({"task": task, "done": False})
elif choice == "2":
for i, todo in enumerate(todos, 1):
status = "Done" if todo["done"] else "Pending"
print(f"{i}. {todo['task']} [{status}]")
elif choice == "3":
idx = int(input("Task number: ")) - 1
if 0 <= idx < len(todos):
todos[idx]["done"] = True
elif choice == "4":
break
else:
print("Invalid")
Run this—it’s a full app using everything here.
