← Master Index
Vol. 03 Module 3.1 Lecture

Functions

Python Basics

How This Lesson Fits the Module

Loops repeat code; functions organize repeated code into named, reusable blocks. Every ML codebase is structured as functions: forward(), compute_loss(), train_epoch(), evaluate().

Volume 02 treated functions mathematically—f(x) maps inputs to outputs. Python def is the same idea made concrete: parameters in, return value out, body encapsulated for testing and reuse.

Learning Objectives

By the end of this lesson, students should be able to:

  • Define functions with def, parameters, and return.
  • Distinguish parameters from arguments and positional from keyword arguments.
  • Write functions that compute loss, metrics, and preprocessing steps.
  • Use default parameter values for configurable hyperparameters.
  • Understand scope: local vs global variables in function bodies.
  • Apply docstrings to document AI utility functions.

Defining Functions

Definition — Function

A function is a named block of code that runs when called, accepts parameters (inputs), and optionally returns a result. Functions eliminate duplication and create testable units—the building blocks of ML pipelines.

def mean_squared_error(predictions, targets): """Compute MSE between two equal-length lists.""" if len(predictions) != len(targets): raise ValueError("predictions and targets must match") squared_errors = [(p - t) ** 2 for p, t in zip(predictions, targets)] return sum(squared_errors) / len(predictions) # Call the function — pass arguments preds = [2.0, 4.0, 6.0] tgts = [1.0, 5.0, 5.0] loss = mean_squared_error(preds, tgts) print(f"MSE = {loss:.4f}")

Parameters and Return Values

Concept Role Example
Parameter Variable in function definition def train(lr, epochs)
Argument Value passed at call site train(0.001, 50)
Return Output sent back to caller return val_loss
Default Fallback if arg omitted def train(lr=1e-3)
def z_score(value, mean, std, epsilon=1e-8): """Standardize a scalar; epsilon prevents division by zero.""" return (value - mean) / (std + epsilon) # Positional arguments z = z_score(14.0, 12.0, 2.0) # Keyword arguments — order-independent, self-documenting z = z_score(value=14.0, mean=12.0, std=2.0)

Functions in a Training Pipeline

Data Functions

  • load_dataset(path)
  • normalize_features(X)
  • train_val_split(data, ratio)
  • Pure input→output transforms

Training Functions

  • forward_pass(x, weights)
  • compute_loss(pred, target)
  • train_epoch(model, loader)
  • Side effects: update weights, log metrics
def accuracy(predictions, labels): """Fraction of correct classifications.""" correct = sum(p == l for p, l in zip(predictions, labels)) return correct / len(labels) def evaluate(predictions, labels): """Return dict of metrics — composable reporting.""" return { "accuracy": accuracy(predictions, labels), "num_samples": len(labels), } metrics = evaluate([1, 0, 1, 1], [1, 0, 0, 1]) print(metrics) # {'accuracy': 0.75, 'num_samples': 4}

Scope and None Returns

Variables assigned inside a function are local—invisible outside unless returned. A function without return implicitly returns None.

Definition — Variable Scope

Local scope applies to names assigned inside a function. Global scope applies to module-level names. Functions should prefer returning values over mutating globals—essential for reproducible experiments.

What’s Next in This ModuleThe next lecture, Lists, covers the primary mutable sequence for storing batches of features, labels, and metrics in Python.

Docstrings and Engineering Hygiene

A docstring (triple-quoted string as the first statement) documents purpose, parameters, and return values. In AI teams, clear function contracts reduce integration errors between data, training, and evaluation code.

def clip_gradient_norm(gradients, max_norm=1.0): """ Scale gradients if their L2 norm exceeds max_norm. Args: gradients: list of float gradient values max_norm: maximum allowed L2 norm Returns: list of clipped gradient values """ total = sum(g ** 2 for g in gradients) ** 0.5 if total > max_norm: scale = max_norm / total return [g * scale for g in gradients] return gradients

Common Misconceptions

Misconception 1: “Functions must always return something.”

Why people believe it: Math functions always map to an output.

Reality: Functions like log_metrics() may return None intentionally after writing to a file. Callers should know which functions produce values vs side effects.

Misconception 2: “Default mutable arguments are safe.”

Why people believe it: Defaults look like constants.

Reality: def f(history=[]) shares one list across calls. Use history=None and create a new list inside the function.

Misconception 3: “More parameters means more flexible.”

Why people believe it: Configurability feels professional.

Reality: Functions with 10+ parameters are hard to test. Group related settings into dictionaries or config objects (covered later in this volume).

Quick Knowledge Check

  1. Short Answer: Keyword to define a function? Answer: def.
  2. True/False: A function without return gives None. Answer: True.
  3. Multiple Choice: train(lr=0.01) uses: (a) positional only, (b) keyword argument, (c) global variable, (d) import. Answer: (b).
  4. Short Answer: Difference between parameter and argument? Answer: Parameter is in definition; argument is value passed at call.
  5. True/False: Local variables inside a function are accessible outside it. Answer: False.
  6. Short Answer: Why document functions with docstrings? Answer: Clarify purpose, inputs, outputs for teammates and tools.
  7. Multiple Choice: Best return type for multiple metrics: (a) print only, (b) dict, (c) global vars, (d) None always. Answer: (b).
  8. True/False: Default parameters can make hyperparameters optional. Answer: True.
  9. Short Answer: Write a function signature for accuracy with predictions and labels. Answer: def accuracy(predictions, labels):
  10. Multiple Choice: Mutable default argument pitfall affects: (a) ints, (b) floats, (c) lists/dicts, (d) None. Answer: (c).

Key Takeaways

  • Define functions with def; return values with return.
  • Parameters define the interface; arguments supply values at call time.
  • Default parameters configure hyperparameters with sensible fallbacks.
  • Structure ML code as small, testable functions: loss, metrics, train, evaluate.
  • Prefer returning results over mutating global state.
  • Next: Lists as the workhorse sequence type for batches and records.
Trainer’s Guide

Hands-on idea: Refactor a monolithic training script into compute_loss, train_epoch, and evaluate functions.

Debugging exercise: Demonstrate the mutable default argument bug with a shared history=[] list.

Discussion prompt: Which functions in a pipeline should be pure (no side effects) vs impure (write logs, save checkpoints)?

What’s Next Continue to Lists to store ordered collections of features, predictions, and experiment results.