Prerequisites

This chapter builds on Chapter 4: control flow. Before proceeding, you should be comfortable writing if/elif/else branches, for and while loops, and using comparison and logical operators to control program execution. You also need working knowledge of Python's core data types—str, int, float, list, and dict—since functions you build here will accept these as parameters and produce them as return values. Familiarity with running .py files from the terminal and reading basic tracebacks is expected.

Learning Goals

  1. Define functions with def

    • Define functions with defto encapsulate logic into named, reusable blocks that replace duplicated code across your programs
    • Write syntactically correct function definitions using the def keyword, a descriptive function name, parentheses for the parameter list, and a colon to open the function body
    • Call functions by name with parentheses, distinguishing between defining a function (which registers it) and invoking it (which executes the body)
    • Structure multi-statement function bodies using consistent indentation, understanding that Python uses whitespace—not braces—to determine where a function begins and ends
  2. Use parameters and return values

    • Use parameters and return valuesto create functions that accept input, process it, and produce explicit output for the caller to consume
    • Define positional parameters, keyword parameters with default values, and understand the evaluation order Python follows when matching arguments to parameter names at call time
    • Use the return statement to send a result back to the caller, recognizing that a function without an explicit return yields None by default
    • Accept multiple parameters and return multiple values using tuple packing, enabling functions like parse_coordinate to hand back both latitude and longitude in a single call
    • Differentiate between mutable and immutable arguments, understanding why passing a list into a function and modifying it inside affects the original object while reassigning an int does not
  3. Write docstrings for documentation

    • Write docstrings for documentationthat communicate a function's purpose, expected inputs, and outputs to both human readers and automated tooling
    • Place a triple-quoted string as the first statement inside a function body, making it accessible at runtime via the doc attribute and through Python's built-in help() function
    • Follow the Google or NumPy docstring convention to document each parameter's name, type, and purpose under an Args: or Parameters: heading, giving downstream consumers a consistent reading experience
    • Document return types, possible exceptions (such as ValueError or TypeError), and edge-case behavior so that callers can handle failures without reading the function's implementation
  4. Understand local vs global scope

    • Understand local vs global scopeto predict exactly which variable Python resolves at any point in your code and avoid subtle bugs caused by name shadowing
    • Explain Python's LEGB resolution order—Local, Enclosing, Global, Built-in—and trace how the interpreter walks this chain when it encounters a variable name during execution
    • Demonstrate that variables assigned inside a function are local by default and do not modify or create global variables unless explicitly declared with the global keyword
    • Identify common scope pitfalls such as the UnboundLocalError that occurs when you read a variable before assigning it locally, and the stale-closure problem in loops that capture a loop variable by reference rather than by value

Key Terminology

Function
A named block of code defined with **def** that performs a specific task and can be called repeatedly from different locations in a program.
Parameter
A variable listed inside the parentheses of a function definition that acts as a placeholder for data the function expects to receive when called.
Argument
The actual value passed to a function at call time, which gets bound to the corresponding parameter inside the function body.
Return Value
The object a function sends back to its caller via the **return** statement, allowing the result to be assigned to a variable or used in an expression.
Docstring
A triple-quoted string placed as the first statement inside a function body that documents its purpose, parameters, and return behavior, accessible at runtime through the **__doc__** attribute.
Scope
The region of a program where a particular variable name is visible and can be referenced without raising a **NameError**.
Local Variable
A variable created inside a function body that exists only during that function's execution and is inaccessible from outside the function.
Global Variable
A variable defined at the module level, outside any function, that is readable from anywhere in the module but requires the **global** keyword to be reassigned inside a function.
LEGB Rule
Python's name resolution order—Local, Enclosing, Global, Built-in—that determines which variable the interpreter finds first when a name is referenced.
Default Parameter Value
A value specified in the function definition using the **=** syntax that is used when the caller does not supply an argument for that parameter.
Positional Argument
An argument matched to a parameter based on its position in the function call, where the first argument maps to the first parameter and so on.
Keyword Argument
An argument passed to a function using the **name=value** syntax, allowing the caller to specify parameters in any order and improving readability.
None
Python's built-in singleton object representing the absence of a value, returned implicitly by any function that lacks an explicit **return** statement.
Call Stack
The internal structure Python uses to track active function calls, pushing a new frame when a function is invoked and popping it when the function returns.
Enclosing Scope
The scope of an outer function that surrounds a nested inner function, allowing the inner function to read variables from the outer function's namespace via closure.
global Keyword
A declaration used inside a function to indicate that a variable name refers to the module-level binding rather than creating a new local variable.

On This Page