Comprehensive Python Programming & Control Flow Study Guide

Administrative Logistics & Announcements

  • Course Content & Announcements Correction:
    • Some course announcements from the previous spring term were copied over without updated dates.
    • Specific dates in previous announcements were mismatched (e.g., deleted entries marked with incorrect dates).
    • Clarification emails will be sent out for future schedule corrections to avoid confusion regarding class times.
    • Direct email communication with the instructor should be used for quick clarification on course scheduling.
  • Lab Assignments Schedule:
    • There are currently no graded lab assignments assigned.
    • Lab 1: Lab 1 (originally scheduled for the prior week) will be covered synchronously during the lab session.
    • Lab 1 Content: Focuses on foundational, simple Python operations and environment setup.

Python Strings & Collection Basics

  • Overview of Strings as Data Collections:
    • A string is an immutable collection of characters, including letters, digits, symbols, whitespace, and punctuation marks.
    • String literals can be enclosed in either single quotation marks ('...') or double quotation marks ("...").
    • Syntax Rule: Quotation mark usage must be consistent. A string starting with a single quote must end with a single quote, and a string starting with a double quote must end with a double quote.
  • String Operations:
    • Concatenation: Strings are joined together into a single new string using the addition operator (+).
    • Indexing: Individual characters within a string are accessed using zero-based indexing inside square brackets ([]).
      • Example: For the string "hello world", accessing index 0 yields 'H' (or 'h').
    • Length Determination: The len() function returns the total count of all characters, including visible characters and spaces.
      • Detailed Calculation Example: Consider the string "this is a string":
        • Visible characters: this (4) + is (2) + a (1) + string (6) = 13 characters.
        • Whitespace characters: 3 blank spaces.
        • Total String Length: 13+3=1613 + 3 = 16
    • Memory Structure: Python strings are self-contained collections. Unlike low-level languages such as C++ or Java, Python strings do not use explicit null-terminator characters (e.g., \0) or end-of-line stoppage characters to signify string termination.

String Formatting & Input Operations

  • Formatted String Literals (f-strings):
    • An f-string is denoted by prefixing the string literal with an f or F (e.g., f"...").
    • Curly braces ({}) define replaceable placeholder expressions inside the string. Expressions inside curly braces can include variables, mathematical calculations, or function calls.
    • Syntax Comparison: Modern Python prefers f-strings over the older .format() method due to superior readability, concise syntax, and convenience.
    • Example 1 (Variable Substitution):
      • Variable: name = "Reiko"
      • Formatted String: f"she said her name is {name}"
      • Output: "she said her name is Reiko"
    • Example 2 (Function Evaluation):
      • Formatted String: f"{name} is {len(name)}"
      • Evaluation: {name} evaluates to "Reiko", and {len(name)} evaluates to standard numerical length 5.
      • Output: "Reiko is 5"
  • User Input via input() Function:
    • The input() function prompts the user for standard input from the console.
    • Syntax: input(prompt_string)
    • Execution Flow: Displays the prompt string, pauses execution to present a text box/entry line, and waits for the user to type a response and press Enter.
    • Type Casting Rule: The input() function always returns the user's entry as a string (str), regardless of what characters or numbers are entered.
      • Example: Entering numerical digits like 505 into username = input("What's your name?") yields username = "505", where type(username) evaluates to <class 'str'>.
    • Manual Numeric Conversion: To use input values in arithmetic operations, the returned string must be explicitly cast using int() or float().
      • Code Sequence: ```python username = input("What's your name?") # User inputs: 505 number = int(username) # Explicitly cast to integer # type(number) now evaluates to
# Console Output & Escape Characters

*   **Standard Output with `print()`**:
    *   Accepts single items, formatted strings, or multiple comma-separated arguments.
    *   Comma-separated items in a `print()` call are output sequentially, separated by a default single space. The commas themselves are not printed.
*   **Keyword Argument: `end`**:
    *   By default, `print()` appends a newline character (`\n`) at the end of its output.
    *   The `end` parameter overrides this default ending character with custom strings or symbols.
    *   *Example*: Formatting percentages directly:
        ```python
        n = 5 * (1 / 100)  # Numerical calculation yielding percentage
        print(5, end="%")  # Outputs: 5%
  • Quotes and Escape Characters:
    • Enclosing double quotes directly inside a double-quoted string literal causes a syntax error because Python interprets the second double quote as the string delimiter.
    • Solution 1 (Quote Alternation): Enclose the string in single quotes if double quotes are needed inside, e.g., 'My name is "James"'.
    • Solution 2 (Backslash Escaping): Prefix inner double quotes with a backslash (\"), e.g., "My name is \"James\"".
    • Common Escape Sequences:
      • \": Literal double quotation mark.
      • \': Literal single quotation mark.
      • \\: Literal backslash.
      • \n: Linefeed / New line.
      • \t: Horizontal tab.

Control Flow: Branching Statements

  • if-elif-else Structure:
    • Provides conditional branching based on logical comparisons and boolean expressions.
    • Execution Logic:
      • Evaluates the initial if statement condition.
      • If True, executes the indented code block (indented one standard unit to the right) and skips all remaining branches.
      • If False, sequentially evaluates subsequent elif (else if) conditions.
      • If all prior conditions evaluate to False, the else block executes.
    • Flexibility: elif and else blocks are optional. Multiple elif blocks can be chained together.
  • Pattern Matching with match-case:
    • Introduced for structural pattern matching, structurally optimized for discrete string and object matching (analogous to switch-case in other programming languages).
    • Distinction: if-else is primary for complex logical evaluation and mathematical comparisons, whereas match-case provides cleaner syntax for direct structural and literal string matching.
    • Wildcard Case (case _): Acts as the default fallback branch, equivalent to the else block in an if-else chain.
    • Syntax & Advanced Pattern Matching Example: ```python command = "run" match command: case "run": print("Executing run command") case "speak" | "say hi": # Logical OR within string matching print("The robot says hi") case _ if command.isdigit(): # Conditional guard using string methods print("Numeric command processed") case _: # Wildcard default match print("Unknown command")
    *   **String Methods used in Guards**: `.isdigit()`, `.isalpha()`, `.isidentifier()`.

# Control Flow: Iterative Loops (`for` and `while`)

*   **Fundamental Loop Concepts**:
    *   Iteration executes a block of code multiple times.
    *   *Historical Context*: Primitive programming languages (e.g., early Pascal variations) lacked structured high-level loop constructs, relying instead on explicit jump statements to return to instructions.
*   **`for` Loops**:
    *   **Fixed Numerical Iterations with `range()`**:
        *   `range(stop)`: Generates integers from 00 up to stop1\text{stop} - 1.
            *   *Example*: `range(4)` generates sequence `0, 1, 2, 3` (executes exactly 4 times).
        *   `range(start, stop)`: Generates integers from start\text{start} up to stop1\text{stop} - 1.
            *   *Example*: `range(4, 8)` generates sequence `4, 5, 6, 7` (executes 4 times).
        *   `range(start, stop, step)`: Generates integers from start\text{start} up to stop1\text{stop} - 1, incrementing by step\text{step}.
            *   *Example*: `range(4, 20, 2)` generates sequence `4, 6, 8, 10, 12, 14, 16, 18`.
    *   **Direct Iteration over Collections**:
        *   Loops directly over items in lists, tuples, sets, or dictionaries.
        *   *Example*: `for animal in animals:` assigns each item sequentially to `animal`.
    *   **Indexed Iteration with `enumerate()`**:
        *   Generates paired tuples containing an incremental index counter and the collection item.
        *   *Pythonic Pattern*: `for i, value in enumerate(animals):` allows simultaneous access to index `i` (for `animals[i]`) and item `value`.
    *   **Loop Variable Persistence**: The iteration counter variable in a Python `for` loop retains its final assigned value in the enclosing scope after the loop terminates.
        *   *Example*: Printing variable `i` outside a completed `for i in range(4, 20, 2):` loop outputs `18`.
*   **`while` Loops**:
    *   Executes repeatedly as long as a specified boolean condition remains `True`.
    *   Used when the precise number of required iterations is unknown beforehand.
    *   **Infinite Loop Risk**: The loop condition state variable **must** be updated within the loop body. If the variable is not updated, the loop will run indefinitely.
    *   *Example*:
        ```python
        x = 0
        while x < 4:
            print(x)
            x += 1  # State modification prevents infinite execution

Functions, Data Types, & Type Hinting

  • Function Definitions:
    • Defined using the def keyword, followed by the function name, parameter list in parentheses, and a colon (:).
    • The function body must be indented to the right.
    • Functions execute only when explicitly invoked.
  • Function Invocations & Arguments:
    • Positional Arguments: Parameters are assigned based on the order passed in the call (e.g., add(5, 6) passes 5 to the first parameter and 6 to the second).
    • Keyword Arguments: Parameters are assigned by explicitly naming them in the call (e.g., add(y=6, x=5)). Order does not matter when keywords are specified.
  • Operator Overloading with +:
    • If both operands are integers (int + int), + performs arithmetic addition (5+6=115 + 6 = 11).
    • If both operands are strings (str + str), + performs string concatenation ("5" + "6" = "56").
    • If operands are mixed types (e.g., int + str), Python raises a TypeError (unsupported operand type(s) for +).
  • Function Type Hinting:
    • Type hints document intended argument data types and return types.
    • Syntax: def add_numbers(a: int, b: int) -> int:
      • a: int indicates parameter a is expected to be an integer.
      • -> int indicates the return value is expected to be an integer.
    • Non-Enforcement Rule: Type hints in Python are purely for code readability, documentation, and static analysis tools. They do not strictly enforce data types at runtime. Passing incompatible types (e.g., strings to integer-hinted parameters) will not be blocked by the interpreter until an incompatible operation is executed.

Exception & Error Handling (try-except-else-finally)

  • Purpose: Prevents program execution from crashing when runtime errors or invalid operations occur.
  • Structure & Execution Flow:
    • try: Encloses code that might potentially throw/raise an exception.
    • except: Triggers when an error occurs inside the try block. Can intercept specific built-in exception types (e.g., except IndexError as e:, except TypeError:, except ZeroDivisionError:).
    • else: Executes only if the try block completed successfully without raising any exceptions.
    • finally: Executes always, regardless of whether an exception occurred, was caught, or was avoided. Ideal for resource cleanup.
    • raise: Explicitly raises a specific runtime error intentionally (e.g., raise RuntimeError).
  • Comprehensive Exception Handling Example: ```python try: # Attempting to access an out-of-bounds index on a 2-element list element = my_list[4] except IndexError as e: print("Warning: Index out of bound") except (TypeError, NameError): pass # 'pass' acts as a silent placeholder block else: print("Execution successful: All good") finally: print("Program execution complete")
# Variable Scope: Global, Local, and Nonlocal

*   **Global Scope**:
    *   Variables declared at the outermost, left-most indentation level exist in the global scope.
    *   Global variables are readable throughout the module, but modifying a global variable inside a local function scope requires explicit declaration.
*   **Local Scope**:
    *   Variables declared inside a function body belong to that function's local scope.
    *   Assigning a value to a variable inside a function creates a new local variable by default, leaving any identically named global variable untouched.
*   **`global` Keyword**:
    *   Used within a local scope to declare that operations on a variable target the outer global instance.
    *   *Trace Example*:
        ```python
        x = 5  # Global variable x

        def set_x(num):
            x = num  # Creates a LOCAL variable x; global x remains 5

        def set_global_x(num):
            global x  # Binds local reference to global x
            x = num  # Updates global x to 96
  • nonlocal Keyword:
    • Used specifically inside nested functions (functions defined inside other functions).
    • Binds a variable to the nearest outer (enclosing) non-global function scope.
    • Constraint: nonlocal cannot bind directly to global scope variables. Attempting to use nonlocal on a variable that exists only in the global scope causes a syntax binding error (nonlocal x is non-binding).
    • Trace Example: ```python def outer_function(): x = 43 # Outer local variable def nested_function(): nonlocal x # Binds to outer_function's x x = 9666 # Modifies outer_function's x to 9666 nested_function() print(x) # Prints 9666
# Advanced Arguments: `*args` and `**kwargs`

*   **Dynamic Argument Passing**:
    *   Used when a function needs to accept an arbitrary, unknown number of input parameters.
*   **Single Asterisk (`*args`)**:
    *   Pointers to positional argument lists.
    *   Packs arbitrary positional arguments into a single **tuple**.
*   **Double Asterisk (`**kwargs`)**:
    *   Pointers to keyword argument pairs.
    *   Packs arbitrary keyword arguments into a single **dictionary**.
*   **Syntax Definition**:
    ```python
    def execute_all(*args, **kwargs):
        print(args)    # Outputs tuple of positional arguments
        print(kwargs)  # Outputs dictionary of keyword arguments
  • Practical Application (Geometric Area Calculation):
    • A single generic shape function can inspect len(args) to apply different formulas dynamically:
      • 1 Parameter (side\text{side}): Computes square area: Area=side2\text{Area} = \text{side}^2
      • 2 Parameters (base,height\text{base}, \text{height}): Computes triangle area: Area=12×base×height\text{Area} = \frac{1}{2} \times \text{base} \times \text{height} or rectangle area: Area=width×height\text{Area} = \text{width} \times \text{height}

Functional Programming Hacks & Comprehensions

  • Lambda Functions:
    • Inline, anonymous single-line functions.
    • Syntax: lambda param1, param2: expression
    • Example: add = lambda x, y: x + y replaces explicit def definitions for simple one-line calculations.
  • Built-in Functional Tools:
    • map(function, iterable, ...):
      • Applies a function to every item in an iterable and returns a modified iterator.
      • Type Conversion Example: map(float, [1, 2, 3]) converts items to floating point values [1.0, 2.0, 3.0].
      • Multi-Iterable Element-Wise Comparison: list(map(max, [1, 2, 3], [4, 2, 1])) evaluates pairwise maximums to return [4, 2, 3].
    • filter(function, iterable):
      • Applies a predicate boolean function to each element, retaining only elements where the function returns True.
      • Example: list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) evaluates 3, 4, 5 as False and 6, 7 as True, returning [6, 7].
  • zip(*iterables) Function:
    • Pairs elements from multiple collections positional index by index, returning an iterator of tuples.
    • Example: zip(["apple", "banana", "cherry"], [2, 5, 12]) produces [("apple", 2), ("banana", 5), ("cherry", 12)].
    • Unequal Length Behavior: Truncates automatically to match the length of the shortest input iterable; trailing elements of longer iterables are discarded.
  • Comprehensions:
    • Provides high-performance, concise syntax for creating collections (faster execution than traditional for loop population).
    • List Comprehension:
      • Syntax: [x for x in sequence if condition]
      • Example: [x for x in [3, 4, 5, 6, 7] if x > 5] yields [6, 7].
    • Set Comprehension:
      • Syntax: {x for x in sequence if condition}
      • Example: {x for x in "abcdef" if x not in "abc"} filters out characters 'a', 'b', and 'c', automatically removing duplicate entries to yield set {'d', 'e', 'f'}.
    • Dictionary Comprehension:
      • Syntax: {key_expr: value_expr for item in sequence}
      • Example: {x: x**2 for x in range(5)} generates key-value pairs mapping integers to their squares: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}.

Lecture Discussion & Student Q&A

  • Formatting Notations:
    • Student Question: Does the f prefix in f-strings function as a print call?
    • Response: No. The f prefix is a string literal notation marking the string as formatted. Printing requires wrapping the f-string inside print(), e.g., print(f"...").
  • Pattern Matching Fall-Through:
    • Student Question: In match-case blocks, does execution fall through to check subsequent cases after finding a match?
    • Response: No. Execution evaluates sequentially from top to bottom. Once a case match is found, Python executes that case block and exits the entire match-case construct entirely.
  • String Operands in Generic Add Functions:
    • Student Question: What happens if two string arguments (e.g., "5" and "6") are passed into a basic addition function returning x + y?
    • Response: The function returns string concatenation ("56"), because the + operator joins string operands.