{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "---\n", "title: \"Chapter 3: Functions\"\n", "---" ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "[](https://colab.research.google.com/github/sambaiga/ds-mlops-path/blob/main/tutorials/01-python-basics/03-functions.ipynb) [](https://raw.githubusercontent.com/sambaiga/ds-mlops-path/main/tutorials/01-python-basics/03-functions.ipynb)" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "Your grade-analysis pipeline normalises exam scores, flags outliers, and computes pass rates. The normalisation formula appears in three places in the same file. A month later you discover the threshold was wrong. You fix it in two places. The third copy, buried in the export section, stays wrong. The report ships with incorrect numbers.\n", "\n", "A function solves this. You write the logic once, give it a name, and call it from anywhere. Chapter 2 put your programs in motion with decisions and loops; this chapter adds naming so that motion can be reused. The energy theft detector you are building by Chapter 27 will need dozens of these named calculations: parse a meter reading, flag a threshold breach, compute a rolling mean. This chapter is where you learn to write them.\n", "\n", "By the end you will write functions that accept any number of arguments, use standard library modules, and return structured results. Chapter 4 (`04-classes.ipynb`) takes this further: it shows how to bundle functions and the data they operate on into a single named object, called a class." ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "::: {.callout-note collapse=\"true\" icon=false}\n", "## Learning objectives\n", "\n", "By the end of Chapter 3 you will be able to:\n", "\n", "| # | Skill | Covered in |\n", "|---|---|---|\n", "| 1 | Define functions with positional, default, and keyword-only parameters | Sec. 1 |\n", "| 2 | Write Google-style docstrings | Sec. 1 |\n", "| 3 | Use lambda expressions as sort keys and with `map()` / `filter()` | Sec. 2 |\n", "| 4 | Accept variable arguments with `*args` and `**kwargs` | Sec. 3 |\n", "| 5 | Use `math`, `json`, and `datetime` from the standard library | Sec. 4 |\n", ":::" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "## 1. Functions\n", "\n", "You need to compute a weighted grade. You could write the arithmetic inline every time you need it, but the day the weighting changes you have to find and update every copy.\n", "\n", "A function wraps that arithmetic under a name. Write it once; call it anywhere.\n", "\n", "{fig-alt=\"Labeled diagram of a def statement showing the def keyword, function name, parameters with type hints, a default value, and the return type annotation.\"}" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "
def name(param: type, param2: type = default) -> return_type:def declares the functionsnake_case= default makes a parameter optional; callers may omit it-> return_type states what the function produces; omit for Nonereturn sends a value back to the callerdef fn(x: float, y: float) -> float:\n",
" \"\"\"One-sentence summary.\n",
"\n",
" Args:\n",
" x: What x means.\n",
" y: What y means.\n",
"\n",
" Returns:\n",
" What the function produces.\n",
" \"\"\"\n",
" ...\n",
"def add_score(score, history=[]):None as the sentinel and create the list inside the function body when history is None.\n",
"grade_letter: it takes a numeric score and returns the letter grade.classify_cohort: it takes a list of scores and returns a Counter mapping each letter grade to the number of students who earned it. Use grade_letter from the cell above.\n",
"accept_login: it checks a username and password against a dict of approved users and returns True if both match, False otherwise.\n",
"map() transform, or a filter() predicate. If the logic is more than one expression, or if you need it in more than one place, write a named function instead.\n",
"filter and sorted, write a one-liner that returns the names of students with GPA >= 3.5, sorted by GPA descending.\n",
"*args collects any number of positional arguments into a tuple.**kwargs collects any number of keyword arguments into a dict.*scores or **attrs work equally well. The * and ** are what matter.\n",
"log_cohort_stats to also include a timestamp key in the returned dict. Use datetime.now(tz=UTC) from the datetime module and format it with .isoformat().\n",
"import math gives you math.sqrt(), math.pi, etc.from math import sqrt, pi imports names directly; use this when you need just one or two items.process_records(rows) that takes a list of raw row dicts (each has name, scores as a list of floats, and major) and returns a list of summary dicts with keys: name, major, mean, grade.score_summary from Section 1 to get the mean, and grade_letter from Activity 1 to get the grade.\n",
"moving_window_average: it replaces each value with the mean of the values within n_neighbors positions on each side. Edge values use whatever neighbors are available.\n",
"