Free Study Material
Every program you've written so far ran one line after another, top to bottom, with no choices along the way. This chapter starts decision-making — beginning with the three basic ways a program's execution order can go.
Control flow is the order in which a program's statements actually execute:
As covered already, Python marks out which lines belong to the same block using consistent indentation, not braces.
marks = 75
if marks >= 40:
print("You have passed.")
print("Result processing complete.")
The print() line directly under if marks >= 40: is indented, so it belongs to that if's block. The final print() is back at the original indentation level — outside the if block — so it runs regardless of whether marks >= 40 is True or False.
Warning: Indenting two lines of the same block by different amounts raises an IndentationError — Python treats indentation as part of the code's actual meaning.
Selection is what lets a program respond differently depending on its data, rather than doing the exact same fixed sequence every single time it runs — the rest of this chapter builds up increasingly capable ways to express that choice.
Control flow is the order statements execute in: sequential (top to bottom), selection (choosing a path), and iteration (repeating a block) — Python marks out each block using consistent indentation.
By default, Python runs code Sequentially (top to bottom). But what if you only want to run a line IF the user is over 18? Or what if you want to repeat a task 100 times? This is Flow of Control. We use logic to divert the "path" of the program.
All statements in a single "block" must have the same level of indentation. Usually, this is 4 spaces or 1 Tab. If you get this wrong, Python will throw an IndentationError.
Line 1, then Line 2, then Line 3. Standard flow.
Deciding which path to take using if, elif, and else.
Repeating a block of code using for or while.
The simplest kind of selection is a single yes/no check: run a block only if a condition is true, otherwise skip it entirely.
if condition:
statement(s)
condition is any expression evaluating to True or False. If True, the indented block runs. If False, the block is skipped completely, and the program continues after it.
temperature = 40
if temperature > 35:
print("Heatwave warning issued.")
print("Weather check complete.")
temperature > 35 is True (40 > 35), so the warning prints, then "Weather check complete." prints regardless, since it's outside the if block. If temperature were 30, the warning would be skipped entirely.
Note: Anifwith no matchingelsesimply does nothing when its condition isFalse— no error, no stopped program.
An if block only ever runs when its condition is exactly True — which is why writing the condition correctly, using the right relational or logical operator, matters as much as writing the block itself.
if condition: runs its indented block only when condition is True; when it's False, the block is skipped and the program continues after it, with no error either way.
The if statement is used for Selection. It allows the program to test a condition: if the condition is True, the program "selects" a specific block of code to run. If the condition is False, the program simply ignores that block. This is how we make programs "smart" enough to respond to different data.
The structure of a simple if follows a specific "grammar" that Python requires:
if.x > 5) that gives True or False.
# Program to demonstrate the simple if statement
score = 94
if score >= 90:
print("Excellent work!")
print("You qualify for the KV Coders Scholarship.")
print("Please collect your certificate.")
print("Program execution complete.")
| SyntaxError | Forgetting the : at the end of the if line. |
| IndentationError | Not indenting the statements inside the if block. |
| Logic Error | Using = (assignment) instead of == (comparison). |
A plain if only handles one path — do something, or do nothing. Most real decisions need a second path for when the condition is false.
if condition:
statement(s) run when condition is True
else:
statement(s) run when condition is False
Exactly one of the two blocks runs, every time — never both, never neither.
marks = 32
if marks >= 40:
print("Result: PASS")
else:
print("Result: FAIL")
marks >= 40 is False (32 is less than 40), so the if block is skipped and the else block runs instead, printing Result: FAIL. If marks were 55, the if block would run and print Result: PASS.
Note:elsenever takes its own condition — it simply means "whenever theifabove it was False." Writingelse ifis not valid Python syntax at all.
Because exactly one branch always runs, if-else is the right structure whenever a decision genuinely has two outcomes and both must be handled — unlike a plain if, which is only appropriate when doing nothing is itself an acceptable outcome.
if-else runs exactly one of two blocks: the if block when its condition is True, or the else block when it's False — one of the two always executes.
The if-else statement provides two paths for the program. Unlike the simple if, which either runs code or does nothing, if-else ensures that exactly one of the two blocks will execute. If the condition is True, the first block runs; otherwise, the else block runs.
Note that the else keyword never takes a condition. It is the "catch-all" for when the if fails.
# Program to check if a number is Even or Odd
num = 15
if num % 2 == 0:
print(num, "is an Even number.")
print("It is divisible by 2.")
else:
print(num, "is an Odd number.")
print("It leaves a remainder when divided by 2.")
print("Calculation finished.")
if-else only chooses between two outcomes. Many real decisions — like assigning a grade from a mark — have more than two possible outcomes.
if condition1:
statement(s)
elif condition2:
statement(s)
else:
statement(s)
Python checks each condition top to bottom and runs the block belonging to the first one that's True — every condition below it is skipped, even if it would also have been True. elif can repeat as many times as needed; else is optional and always goes last.
marks = 78
if marks >= 90:
print("Grade: A")
elif marks >= 75:
print("Grade: B")
elif marks >= 60:
print("Grade: C")
else:
print("Grade: D")
Python checks marks >= 90 first — False. It then checks marks >= 75 — True — so Grade: B prints, and every condition below it is skipped, even though marks >= 60 would also have been True.
Warning: Ordering matters. Writing the conditions from lowest to highest instead would let a high mark match the wrong, lower boundary first. Write ladders from the strictest condition down to the loosest.
"First match wins, then stop" is the one rule this structure depends on — exactly why a grading ladder's boundaries must be ordered strictest-first, top to bottom.
if-elif-else checks each condition in order and runs only the first one that's True, skipping every condition after it — order boundary-based ladders from strictest to loosest.
Sometimes we need to check multiple conditions in a sequence. The if-elif-else ladder allows Python to check conditions one by one from top to bottom. As soon as it finds a True condition, it executes that block and skips the rest of the ladder. The elif is short for "else if."
You can have as many elif blocks as you need, but you can only have one if and one else.
# Program to calculate Grade based on Marks
marks = 65
if marks >= 90:
print("Grade: A+ (Outstanding)")
elif marks >= 80:
print("Grade: A (Excellent)")
elif marks >= 70:
print("Grade: B (Good)")
elif marks >= 33:
print("Grade: C (Pass)")
else:
print("Grade: F (Fail/Re-appear)")
print("Evaluation Complete.")
| Situation | Best Structure |
| One choice (Yes or do nothing) | if |
| Two choices (Either A or B) | if-else |
| Multiple choices (Select one of many) | if-elif-else |
Selection chooses between paths, but every path still only runs once. This topic covers iteration — repeating a block for as long as a condition stays true.
while condition:
statement(s)
Python checks condition before each pass. As long as it's True, the block runs, then Python checks again. The moment it's False, the loop stops. Something inside the loop body must eventually make condition False — usually by updating a counter — or the loop never stops (an infinite loop).
count = 1
while count <= 5:
print("Count is:", count)
count += 1
print("Loop finished.")
count starts at 1. Each pass prints its value, then count += 1 increases it. Python checks count <= 5 before every pass: True for 1 through 5 — five passes — and False once count becomes 6, which is when the loop stops.
Warning: Removingcount += 1would leaveconditionTrueforever, sincecountnever changes — the loop would never stop.
A while loop is the right choice when you don't know in advance exactly how many times a loop needs to run — only the condition under which it should keep going.
while condition: repeats its block for as long as condition stays True, checked before every pass — the body must eventually make the condition False, or the loop runs forever.
The while loop is a control flow statement that allows code to be executed repeatedly based on a given Boolean condition. It is often called a "Condition-Controlled Loop" because it runs while a specific condition remains True.
x > 0) that returns True or False.x = x - 1) to eventually stop the loop.
# Program to simulate a Password Check
# 1. Initialization
correct_password = "KVCODERS"
user_attempt = "WRONG_PASS" # Simulating a wrong guess initially
print("System Locked.")
# 2. Condition: Keep running while the attempt is WRONG
while user_attempt != correct_password:
print("Attempt:", user_attempt)
print("Access Denied. Trying again...")
# 3. Update: Simulate the user typing the correct password
# In a real app, this would be: input("Enter Password: ")
user_attempt = "KVCODERS"
print("Access Granted! Welcome User.")
while repeats based on a condition you check yourself. When you already know how many times something should repeat, Python's for loop, paired with range(), is the more natural choice.
for variable in range(...):
statement(s)
range() generates whole numbers, and for runs its block once per number, storing the current one in variable. Three forms: range(stop) (0 up to stop-1), range(start, stop), range(start, stop, step).
for i in range(5):
print("i is:", i)
for num in range(2, 11, 2):
print("Even number:", num)
range(5) generates 0, 1, 2, 3, 4 — five values — so the first loop prints five lines, i is: 0 through i is: 4. range(2, 11, 2) starts at 2, stops one before 11, counting up by 2: 2, 4, 6, 8, 10.
Note:range(stop)never includesstopitself —range(5)produces five values (0through4), not six, a common off-by-one mistake.
This "stops one before" rule matches how valid index positions work: range(len(some_sequence)), covered once sequences like lists are introduced, produces exactly the sequence's valid positions, with no out-of-range value included.
for variable in range(...): repeats once per number range() generates. range(stop) counts from 0; range(start, stop) sets a custom start; range(start, stop, step) also sets the increment — stop itself is never included.
The for loop is used to iterate over a sequence. In Class 11 CS, we primarily use it with the range() function, which generates a specific sequence of numbers for the loop to follow.
| Syntax | Explanation | Example |
range(stop) |
Starts at 0. Stops before the stop value. Increases by 1. |
range(3)Output: 0, 1, 2 |
range(start, stop) |
Starts at start. Stops before the stop value. |
range(2, 5)Output: 2, 3, 4 |
range(start, stop, step) |
Starts at start. Jumps by step value. |
range(1, 10, 2)Output: 1, 3, 5, 7, 9 |
Critical Rule: The stop value is NEVER included in the sequence. It is the "Finish Line"—you stop the moment you touch it.
# 1. ONE ARGUMENT: range(stop)
# Python assumes start=0, step=1
print("--- range(5) ---")
for i in range(5):
print(i, end=" ")
print() # New line
# 2. TWO ARGUMENTS: range(start, stop)
# Python assumes step=1
print("\n--- range(10, 15) ---")
for j in range(10, 15):
print(j, end=" ")
print()
# 3. THREE ARGUMENTS: range(start, stop, step)
# We define everything. Note the output stops before 11.
print("\n--- range(1, 11, 2) ---")
for k in range(1, 11, 2):
print(k, end=" ")
print()
# 4. NEGATIVE STEP: Counting Down
print("\n--- range(5, 0, -1) ---")
for l in range(5, 0, -1):
print(l, end=" ")