{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "771e1741",
   "metadata": {},
   "source": [
    "# Iterators & Generators"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd36f9cf",
   "metadata": {},
   "source": [
    "**Learning goals** — By the end of this chapter you will be able to:\n",
    "\n",
    "- Explain Python's **iterator protocol** (`__iter__` / `__next__`) and use `iter()` and `next()` manually\n",
    "- Use built-in lazy iterators: `enumerate()`, `zip()`, `map()`, `filter()`, and `reversed()`\n",
    "- Build **custom iterator classes** that implement the full iterator protocol\n",
    "- Write **generator functions** using `yield` to produce values lazily\n",
    "- Create **generator expressions** as a memory-efficient alternative to list comprehensions\n",
    "- Design multi-step data pipelines using chained generators\n",
    "\n",
    "Iterators and generators are the backbone of Python's memory-efficient data processing. Everything from `for` loops to file reading to pandas relies on this protocol.\n",
    "\n",
    "<h2>Chapter flow</h2>\n",
    "\n",
    "```{tableofcontents}\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
