Control_Flow_and

1

Conditional Statements

▶

Conditional statements allow a program to make decisions by executing different code blocks based on whether a condition evaluates to true or false. Python provides if, elif, and else constructs to express branching logic clearly and concisely.

  • The if Statement: An if statement evaluates a Boolean expression and executes its indented block only when the result is True. Python uses indentation (typically four spaces) rather than braces to define the scope of a conditional block, so consistent formatting is essential. Any expression that returns True or False can serve as the condition, including comparisons and logical operators.
  • The elif Clause: elif is evaluated only if all preceding if and elif conditions were False, making it an efficient way to test a series of mutually exclusive cases. Any number of elif clauses can follow a single if statement, and using them instead of multiple independent if statements avoids unnecessary condition evaluations once a match is found.
  • The else Clause: else does not take a condition; it runs automatically when all prior conditions are False, acting as a catch-all fallback. Only one else clause is permitted per if-elif-else chain, and it must appear last. Including an else clause is good practice for handling edge cases and unexpected inputs.
  • Comparison and Logical Operators: Comparison operators such as ==, !=, <, >, <=, and >= return True or False by comparing two values. The and operator returns True only if both operands are True, while the or operator returns True if at least one operand is True. The not operator negates a Boolean expression, turning True to False and vice versa.
  • Nested Conditionals: A nested conditional is an if statement contained within the block of another if, elif, or else clause, and each nested level requires an additional level of indentation. Excessive nesting can make code harder to read and maintain; flattening logic with logical operators is often preferred. For example, two nested conditions can frequently be combined into a single condition using and.
# Example: if-elif-else chain
score = 78

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
else:
    grade = "F"

print(grade)  # Output: C
NotesConditional statements allow a program to make decisions by executing different code blocks based on whether a condition evaluates to true or false. This topic covers if, elif, and else constructs in Python. Slides: 1, 2, 3, 4, 5.
2

for Loops and the range() Function

▶

The for loop iterates over a sequence of items, making it ideal for processing collections of data. The range() function generates numeric sequences commonly used to control loop iterations, and tools like enumerate() add further flexibility when both index and value are needed.

  • The for Loop: The loop variable takes on the value of each successive item in the iterable on each iteration, and the loop body executes once for every item in the sequence. Any iterable object — including lists, tuples, strings, and dictionaries — can be used with a for loop, making it a versatile and widely used control structure in Python.
  • The range() Function — Basic Form: range(n) generates integers from 0 up to but not including n, making it the simplest way to repeat an action a fixed number of times. range(start, stop) generates integers from start up to but not including stop, giving control over where the sequence begins.
  • The range() Function — Step Form: range(start, stop, step) generates integers from start to stop, incrementing by step each time, which allows for skipping values or counting backwards with a negative step. range() produces values lazily, meaning values are computed on demand rather than stored all at once, making it memory-efficient for large sequences.
  • Iterating with an Index Using enumerate(): enumerate(iterable) returns pairs of (index, value) for each item in the sequence, so both the position and the value are available inside the loop. Using enumerate() avoids the need for a separate counter variable, and its optional start parameter allows the index to begin at a value other than zero.
  • Looping Over Numeric Ranges in Engineering: range() is ideal for stepping through evenly spaced numeric intervals common in engineering computations, such as time steps in a simulation. Combining range() with len() allows iteration over the indices of any list or array, and careful selection of start, stop, and step values prevents off-by-one errors in numerical work.
# Example: range() with step and enumerate()
values = [10.5, 20.3, 15.8, 9.1]

for i, v in enumerate(values, start=1):
    print(f"Sample {i}: {v}")

# Counting down with a negative step
for n in range(5, 0, -1):
    print(n)
NotesThe for loop iterates over a sequence of items, making it ideal for processing collections of data. The range() function generates numeric sequences commonly used to control loop iterations. Slides: 1, 2, 3, 4.
3

while Loops

▶

A while loop repeats a block of code for as long as a specified condition remains True, making it suitable for situations where the number of iterations is not known in advance. Understanding how to structure the condition and guarantee termination is essential to using while loops safely.

  • The while Loop Structure: The condition is evaluated before each iteration; if it is False initially, the loop body never executes at all. The loop body must include a statement that changes the condition's outcome to eventually terminate the loop, otherwise the program will run forever. while loops are well suited for event-driven loops, convergence checks, and user-input validation where an exact iteration count cannot be predetermined.
  • Infinite Loops and Loop Guards: An infinite loop results when the loop condition is never updated to become False, causing the program to hang. Common causes include forgetting to increment a counter or inadvertently using an always-True condition such as while True: without a break. A loop guard is a variable or condition deliberately placed in the loop body to ensure the loop will eventually terminate.
  • Comparing for and while Loops: Use a for loop when the number of iterations or the sequence to iterate over is known before the loop starts, as it expresses intent more clearly in those cases. Use a while loop when the loop must continue until a runtime condition changes, such as reading sensor data until a threshold is exceeded. Both loop types can solve many of the same problems, but choosing the appropriate one improves code clarity and reduces the risk of logic errors.
# Example: while loop for convergence check
estimate = 1.0
target = 2.0
tolerance = 0.001

while abs(target - estimate) > tolerance:
    estimate += 0.1
    print(f"Current estimate: {estimate:.3f}")

print("Converged!")
NotesA while loop repeats a block of code for as long as a specified condition remains True, making it suitable for situations where the number of iterations is not known in advance. Slides: 1, 2, 3.
4

Loop Control: break and continue

▶

The break and continue statements provide fine-grained control over loop execution, allowing early termination or skipping specific iterations without exiting the loop entirely. Used thoughtfully, they produce efficient and readable loop structures.

  • The break Statement: break exits the loop immediately, regardless of whether the loop condition is still True, and execution continues with the first statement after the loop's closing block. In nested loops, break only terminates the innermost loop in which it appears, leaving outer loops unaffected. break is often paired with an if statement to conditionally exit a loop once a target value or state is reached.
  • The continue Statement: continue does not exit the loop; it only skips the remainder of the current iteration and moves on to the next one. After continue, a for loop advances to the next item and a while loop re-evaluates its condition before proceeding. continue improves readability by avoiding deeply nested if statements inside loop bodies — instead of wrapping valid-case logic in an if, you skip invalid cases up front.
  • The else Clause on Loops: A loop's else block runs after the loop finishes all iterations without hitting a break statement. If break is executed, the else block is skipped entirely, which makes this construct particularly useful for implementing search logic with a clear "not found" outcome. This pattern eliminates the need for a separate flag variable to track whether a loop completed normally.
  • Practical Use Cases for break and continue: Use break to stop iterating once a target condition or result is found, saving unnecessary computation on the remaining items. Use continue to skip invalid, missing, or out-of-range values during data processing without interrupting the overall loop. Combining break and continue with conditional logic creates efficient, readable loop structures that clearly express the programmer's intent.
# Example: break, continue, and loop else
data = [4, -1, 7, 0, 3, -2, 5]

for value in data:
    if value < 0:
        continue          # skip negative values
    if value == 0:
        break             # stop if a zero is encountered
    print(f"Processing: {value}")
else:
    print("All values processed without hitting zero.")
NotesThe break and continue statements provide fine-grained control over loop execution, allowing early termination or skipping specific iterations without exiting the loop entirely. Slides: 1, 2, 3, 4.