Unit 2: Conditional and Iterative Statements
I. Orientation: Control Flow in Python
A Python program executes statements top-to-bottom unless a control flow statement alters that order. This unit covers the two alterations available: selection (run a block only if a condition holds) and iteration (run a block repeatedly). Both depend on evaluating an expression to a truth value, so the unit also covers the operators that produce truth values, the % operator that supplies most of the arithmetic tests, and the random module that supplies unpredictable data to loop over.
Defining properties and conventions assumed throughout:
- Block structure by indentation: Python has no
begin/endor braces. A compound statement consists of a header line ending in a colon and an indented body (conventionally 4 spaces). Consistent indentation is syntax, not style. - The
booltype: Has exactly two values,TrueandFalse(capitalised), which are subclasses ofintwith values 1 and 0 —True + Trueis2. - Truthiness: Any object may be used where a condition is expected. Falsy values are
False,None,0,0.0,"",[],(),{}; everything else is truthy. - Statement versus expression:
if,whileandforare statements — they perform an action and have no value.x % 2 == 0is an expression — it has the valueTrueorFalse. - Flow of execution: The order in which lines actually run. Tracing this order by hand (a desk check) is the primary debugging technique for this unit.
- Loop vocabulary: iteration = one pass through the body; loop variable = the name updated each pass; terminating condition = the state that ends the loop; infinite loop = a loop whose condition never becomes false.
II. Operators and Values that Drive Decisions
Selection and iteration are only as expressive as the tests written into them. This section covers the arithmetic operator, the data source, and the two operator families that build those tests.
A. Modulus Operator
The modulus operator % yields the remainder after integer division of the left operand by the right.
- Definition and companion:
a % bis the remainder,a // bis the floor (integer) quotient. They satisfthe identity(a // b) * b + a % b == a.
PYTHON7 % 3 # 1 7 // 3 # 2 -7 % 3 # 2 (sign follows the divisor in Python) 6.5 % 2 # 0.5 (works on floats too) - Divisibility test:
x % n == 0is true exactly whenndividesx. Basis of even/odd tests (x % 2 == 0), leap-year rules, and FizzBuzz-style logic. - Digit extraction:
n % 10gives the last decimal digit,n // 10removes it — the standard pair for digit-sum, palindrome and reverse-number loops. - Wrapping/cycling:
(i + 1) % kcycles indices0,1,…,k−1; clock arithmetic useshour % 12, day-of-week usesd % 7. - Error condition:
b % 0raisesZeroDivisionError, so guard with a conditional before dividing by a user-supplied value.
B. Random Numbers
Programs are deterministic, so "random" numbers come from a pseudo-random generator — a deterministic algorithm whose output passes statistical tests for randomness.
- Import and seed:
import random. The generator holds internal state;random.seed(42)fixes it so a run is reproducible for testing. Without a seed, state is initialised from the system clock/OS entropy. - Core functions:
PYTHONrandom.random() # float in [0.0, 1.0) random.randint(1, 6) # int in 1..6 inclusive (a die) random.randrange(0, 10, 2) # like range(): 0,2,4,6,8 random.uniform(1.5, 3.5) # float in the given range random.choice(['H','T']) # one element of a sequence random.shuffle(deck) # in-place permutation - Scaling by hand:
int(random.random() * n)gives0..n-1;low + int(random.random() * (high - low + 1))generalises it — the arithmeticrandintperforms internally. - Why it belongs here: Random values give conditionals and loops non-trivial input, enabling simulation (dice, coin tosses, Monte Carlo estimates) without file or user input.
C. Boolean Expressions
A Boolean expression is any expression whose value is True or False; the relational operators are its main source.
- The six comparisons:
==(equal),!=(not equal),>,<,>=,<=. Note=is assignment;==is comparison — confusing them is aSyntaxErrorin a condition. - Chaining: Python permits mathematical chaining:
0 <= x <= 100is evaluated as0 <= x and x <= 100, withxcomputed once. - Membership and identity:
in/not intest containment ('a' in 'cat'→True);is/is nottest object identity, correct only for singletons such asNone. - Float caution:
0.1 + 0.2 == 0.3isFalsedue to binary representation; compare with a tolerance,abs(a - b) < 1e-9.
D. Logic Operators
The three logical operators combine Boolean expressions into compound conditions.
and: True only if both operands are true —n % 2 == 0 and n % 3 == 0tests divisibility by 6.or: True if at least one operand is true —ch == 'y' or ch == 'Y'.not: Unary negation —not (x > 10)is equivalent tox <= 10(De Morgan-style rewriting keeps conditions readable).- Short-circuit evaluation:
andstops at the first false operand,orat the first true one. This makes guards possible:if n != 0 and total / n > 5:never divides by zero. - Return value: The operators return an operand, not a bool —
0 or 'x'is'x','a' and 'b'is'b'. - Precedence:
not>and>or, and all comparisons bind tighter than all three; parenthesise mixed expressions for clarity.
III. Selection: Conditional Statements
Selection chooses among alternative blocks by evaluating conditions in order.
A. Conditional
The if statement executes its body only when the condition is truthy.
- Three forms:
PYTHONif x > 0: # simple: one branch print('positive') if x % 2 == 0: # alternative: exactly one of two runs print('even') else: print('odd') if score >= 90: # chained: first true branch wins, rest skipped grade = 'A' elif score >= 80: grade = 'B' else: grade = 'F' - Branch: Each possible path is a branch;
elsehas no condition and is the catch-all. Only one branch of a chain ever executes. - Order matters: In a chained conditional, place the most restrictive condition first — testing
score >= 80beforescore >= 90would label every A as a B. - Empty body: Use
passas a placeholder body, since an indented block cannot be omitted. - Conditional expression:
parity = 'even' if n % 2 == 0 else 'odd'compresses a two-branch assignment into one line.
B. Nested Conditionals
A conditional whose body contains another conditional; the outer condition is a precondition for the inner test.
- Structure and cost: Each level adds an indentation level; readability degrades quickly past two levels.
PYTHONif x == y: print('equal') else: if x < y: print('x is less') else: print('x is greater') - Flattening with
elif: The above is identical toif x == y: … elif x < y: … else: …— prefer the flat form. - Flattening with
and:if 0 < x: if x < 10:becomesif 0 < x < 10:. - Guardian pattern: Nesting is legitimate when the outer test protects the inner one:
if y != 0:wrappingif x / y > 1:.
IV. Iteration: Loop Statements
Iteration repeats a block. Choose while when the number of repetitions is unknown, for when it is known or a sequence is available.
A. While Statements
A while loop re-tests its condition before every iteration and stops when the condition becomes false.
- Semantics: Evaluate condition → if false, exit; if true, run body, repeat. Zero iterations occur if the condition is false initially.
PYTHONn = 27; count = 0 while n != 1: # Collatz sequence length n = n // 2 if n % 2 == 0 else 3 * n + 1 count += 1 - Three obligations: initialise the loop variable before the loop, test it in the header, update it inside the body. Omitting the update gives an infinite loop.
- Termination argument: For the countdown
while n > 0: n = n - 1,nstrictly decreases and is bounded below, so the loop must end. - Sentinel/validation loop: Repeat until input is acceptable —
while True:withif valid: break. break,continue,else:breakexits immediately;continueskips to the next test; a loopelseclause runs only if the loop ended withoutbreak(useful in prime testing).
B. For Loop Statement
A for loop performs definite iteration over the items of an iterable, assigning each in turn to the loop variable.
- Form and
range:range(start, stop, step)producesstart … stop-1;stopis exclusive.
PYTHONtotal = 0 for i in range(1, 11): # 1..10 total += i # accumulator pattern → 55 for ch in 'python': # traversal of a string print(ch, end=' ') - Traversal by index vs by item:
for i in range(len(s))gives positions;for c in sgives characters;for i, c in enumerate(s)gives both. - Counter and accumulator idioms: initialise
count = 0/total = 0before the loop; update inside; report after. - Contrast with
while:forcannot loop forever over a finite iterable and needs no manual update, so it is preferred whenever the iteration count is determinable in advance.
V. Nested Loops and Randomised Repetition
A. Nested For
A for loop inside another; the inner loop completes fully for each single iteration of the outer loop.
- Iteration count: Outer m × inner n = m·n executions of the innermost body — a 3×4 nest runs 12 times.
- Grid/table pattern:
PYTHONfor i in range(1, 4): # rows for j in range(1, 4): # columns print(i * j, end='\t') print() # newline after each row - Dependent bounds:
for j in range(i)makes the inner range grow with the outer variable — the basis of triangular star patterns and pair-comparison loops (for j in range(i+1, n)). - Scope of
break:breakleaves only the innermost loop; use a flag or a functionreturnto leave both.
B. Nested While
The same containment with condition-controlled loops, used when neither bound is known in advance.
- Critical rule: the inner loop's control variable must be re-initialised inside the outer body, otherwise the inner condition is already false on the second outer pass and the inner loop never runs again.
PYTHONi = 1 while i <= 3: j = 1 # re-initialised each outer pass while j <= 3: print(i, j) j += 1 i += 1 - Typical use: input validation inside a menu loop, or digit-processing (
while n > 0) inside a per-number loop.
C. Random Numbers in Loops
Loops turn a single random draw into a data set, which is the basis of simulation.
- Fixed-trial simulation:
forplus a counter estimates a probability.
PYTHONimport random sixes = 0 for _ in range(1000): if random.randint(1, 6) == 6: # conditional inside the loop sixes += 1 print(sixes / 1000) # ≈ 0.167 - Random termination:
while random.random() < 0.5:gives a loop whose trip count is unknown — the naturalwhilecase; the expected number of iterations is 1. - Reproducibility: call
random.seed(0)once before the loop so a failing simulation can be re-run identically while debugging. - Pitfall: drawing the random value outside the loop freezes it; the call must be inside the body to vary per iteration.
VI. Encapsulation and Generalization
These are the two refactoring steps that convert working loop-and-conditional code into reusable code, applied in sequence.
A. Encapsulation
Wrapping a working fragment of code in a function so it can be invoked by name.
- Procedure: take a tested loop, indent it under a
defheader, add a docstring, replace printed results with areturnwhere appropriate. - Effect: local variables (
i,count) become private to the function, removing name clashes; the code becomes a single named unit rather than a block to be re-typed.
PYTHONdef print_squares(): """Print squares of 1..5.""" for i in range(1, 6): print(i * i)
B. Generalization
Replacing a constant inside the encapsulated code with a parameter, so one function covers a family of cases.
- Procedure: identify the hard-coded literal, add it as a parameter, substitute it in the body; supply a default to keep old call sites working.
PYTHONdef print_squares(n=5, base=2): """Print i**base for i in 1..n.""" for i in range(1, n + 1): print(i ** base) - Keyword arguments:
print_squares(base=3, n=4)documents intent at the call site and frees the caller from argument order. - Interface versus implementation: the interface is the parameter list and return value; the implementation is the loop inside. A well-generalized function lets the body change (e.g.
while→for) without breaking callers. - Discipline of the pair: encapsulate first (proving the code works in isolation), generalize second (widening its applicability); repeated together, they build a program from a set of small tested functions rather than one long script.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →