From 457be79f70961035db367c48880e5bbccdbe2acc Mon Sep 17 00:00:00 2001 From: Saqib Bedar <124094939+saqibbedar@users.noreply.github.com> Date: Sun, 4 Oct 2026 16:46:39 +0500 Subject: [PATCH] feat: add detailed comprehension notebooks --- comprehensions/dict/dict.ipynb | 165 ++++++++++++++ comprehensions/generator/generator.ipynb | 235 ++++++++++++++++++++ comprehensions/list/list.ipynb | 267 +++++++++++++++++++++++ comprehensions/set/set.ipynb | 124 +++++++++++ comprehensions/tuple/tuple.ipynb | 55 +++++ 5 files changed, 846 insertions(+) create mode 100644 comprehensions/dict/dict.ipynb create mode 100644 comprehensions/generator/generator.ipynb create mode 100644 comprehensions/list/list.ipynb create mode 100644 comprehensions/set/set.ipynb create mode 100644 comprehensions/tuple/tuple.ipynb diff --git a/comprehensions/dict/dict.ipynb b/comprehensions/dict/dict.ipynb new file mode 100644 index 0000000..842424b --- /dev/null +++ b/comprehensions/dict/dict.ipynb @@ -0,0 +1,165 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6b76bccd", + "metadata": {}, + "source": [ + "# dict comprehension\n", + "\n", + "Syntax:\n", + "\n", + "```py\n", + "new_dict = {key_expression: value_expression for item in iterable}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "a895bb05", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "88fc1603", + "metadata": {}, + "source": [ + "## basic dict comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d9205630", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "traditional way: {'Alice': 5, 'Bob': 3, 'Charlie': 7}\n", + "comprehension way: {'Alice': 5, 'Bob': 3, 'Charlie': 7}\n" + ] + } + ], + "source": [ + "# Map names to their text lengths\n", + "\n", + "names = [\"Alice\", \"Bob\", \"Charlie\"]\n", + "\n", + "# Traditional way\n", + "name_lengths = {}\n", + "for name in names:\n", + " name_lengths[name] = len(name)\n", + "\n", + "print(f\"traditional way: {name_lengths}\")\n", + "\n", + "# comprehension way\n", + "name_lengths = {name: len(name) for name in names}\n", + "print(f\"comprehension way: {name_lengths}\")" + ] + }, + { + "cell_type": "markdown", + "id": "672cea7a", + "metadata": {}, + "source": [ + "## Merging Two Lists into a Dictionary (Using zip)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "daeaf009", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id': 101, 'role': 'admin', 'status': 'active'}\n" + ] + } + ], + "source": [ + "keys = [\"id\", \"role\", \"status\"]\n", + "values = [101, \"admin\", \"active\"]\n", + "\n", + "# comprehension way\n", + "user_profile = {k: v for k, v in zip(keys, values)}\n", + "print(user_profile)" + ] + }, + { + "cell_type": "markdown", + "id": "73d7be84", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "f98b9ee6", + "metadata": {}, + "source": [ + "# Conditional" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "35b3949d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'banana': 10.8, 'mango': 18.0}\n" + ] + } + ], + "source": [ + "prices = {\"apple\": 5, \"banana\": 12, \"mango\": 20}\n", + "\n", + "# Keep if price > 10, then apply 10% discount\n", + "discounted_price = {item: price * 0.9 for item, price in prices.items() if price > 10}\n", + "\n", + "print(discounted_price)" + ] + }, + { + "cell_type": "markdown", + "id": "4976a37d", + "metadata": {}, + "source": [ + "> Note: We use .items() to loop through both the keys and values of the original dictionary at the same time." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.14.7)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/comprehensions/generator/generator.ipynb b/comprehensions/generator/generator.ipynb new file mode 100644 index 0000000..d6ef7da --- /dev/null +++ b/comprehensions/generator/generator.ipynb @@ -0,0 +1,235 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "486c6e96", + "metadata": {}, + "source": [ + "> Generators are one-and-done: once used, they don't exist anymore\n", + "\n", + "# Generator Expressions (The \"Tuple\" Comprehension)\n", + "\n", + "You might think that wrapping a comprehension in parentheses `()` creates a tuple comprehension. However, Python uses that syntax to create a **Generator Expression**.\n", + "\n", + "Instead of building a full collection in memory all at once, a generator creates items **one by one, on demand (lazily)**. This makes them incredibly memory-efficient when dealing with massive datasets." + ] + }, + { + "cell_type": "markdown", + "id": "0fe6c2df", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "5a8bd2e3", + "metadata": {}, + "source": [ + "# 1. The Syntax and Difference\n", + "\n", + "If you print a list comprehension, you see the data. If you print a generator expression, you see the generator object itself." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63b9d11c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 4]\n", + " at 0x7e3bdc5e6670>\n" + ] + } + ], + "source": [ + "# List Comprehension (Immediately allocates memory for 1 million items)\n", + "list_comp = [x**2 for x in range(1000000)]\n", + "\n", + "# Generator Expression (Allocates zero data memory upfront)\n", + "gen_exp = (x**2 for x in range(1000000))\n", + "\n", + "print(list_comp[:3]) # Output: [0, 1, 4]\n", + "print(gen_exp) # Output: at 0x...>" + ] + }, + { + "cell_type": "markdown", + "id": "4945de1b", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "bb8f6dc9", + "metadata": {}, + "source": [ + "# 2. How to Get Values Out of a Generator\n", + "\n", + "Because generators are lazy, you must explicitly ask for the data using a loop, the next() function, or by passing it to a collection constructor." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3889fd38", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "4\n", + "9\n" + ] + } + ], + "source": [ + "numbers = range(1, 4)\n", + "squares_gen = (n**2 for n in numbers)\n", + "\n", + "# Method A: Using next()\n", + "print(next(squares_gen)) # Output: 1\n", + "print(next(squares_gen)) # Output: 4\n", + "\n", + "# Method B: Looping through the rest\n", + "for val in squares_gen:\n", + " print(val) # Output: 9" + ] + }, + { + "cell_type": "markdown", + "id": "a58c3e08", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "fe5a10d0", + "metadata": {}, + "source": [ + "# 3. Turning a Generator into a Tuple" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "657e6a56", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 2, 4, 6, 8)\n" + ] + } + ], + "source": [ + "# Creating an actual tuple\n", + "evens_tuple = tuple(x for x in range(10) if x % 2 == 0)\n", + "\n", + "print(evens_tuple)" + ] + }, + { + "cell_type": "markdown", + "id": "64285021", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "a588cef6", + "metadata": {}, + "source": [ + "## Iterating" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "78990a2c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "4\n", + "9\n" + ] + } + ], + "source": [ + "numbers_gen = (x**2 for x in range(1, 4)) # Generates 1, 4, 9\n", + "\n", + "# Standard for loop way\n", + "for num in numbers_gen:\n", + " print(num)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "64c3c4bc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "red\n", + "green\n", + "blue\n" + ] + } + ], + "source": [ + "# next() way\n", + "colors_gen = (c for c in [\"red\", \"green\", \"blue\"])\n", + "\n", + "print(next(colors_gen)) # Output: red\n", + "print(next(colors_gen)) # Output: green\n", + "\n", + "# You can still loop through whatever is left!\n", + "for remaining in colors_gen:\n", + " print(remaining) # Output: blue" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.14.7)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/comprehensions/list/list.ipynb b/comprehensions/list/list.ipynb new file mode 100644 index 0000000..9e0faa5 --- /dev/null +++ b/comprehensions/list/list.ipynb @@ -0,0 +1,267 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# List Comprehensions (Basic Syntax)\n", + "\n", + "Syntax: \n", + "```py\n", + "new_list = [expression for item in iterable]\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Traditional Loop vs. List Comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 4, 9, 16, 25]\n" + ] + } + ], + "source": [ + "numbers = [1, 2, 3, 4, 5]\n", + "squares = []\n", + "\n", + "for n in numbers:\n", + " squares.append(n**2)\n", + "\n", + "print(squares) # Output: [1, 4, 9, 16, 25]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## List comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 4, 9, 16, 25]\n" + ] + } + ], + "source": [ + "numbers = [1, 2, 3, 4, 5]\n", + "squares = [n**2 for n in numbers]\n", + "\n", + "print(squares)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. List Comprehensions with Conditionals\n", + "\n", + "Syntax:\n", + "\n", + "```py\n", + "new_list = [expression for item in iterable if condition]\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "traditional way: [2, 4]\n", + "comprehension way: [2, 4]\n" + ] + } + ], + "source": [ + "# Keep even numbers only\n", + "\n", + "# Traditional way\n", + "evens = []\n", + "\n", + "for n in numbers:\n", + " if n % 2 == 0:\n", + " evens.append(n)\n", + "\n", + "print(f\"traditional way: {evens}\")\n", + "\n", + "# Comprehension way\n", + "c_evens = [n for n in numbers if n % 2 == 0]\n", + "print(f\"comprehension way: {c_evens}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> How to read it: Loop through numbers, check if n % 2 == 0, and if true, keep n." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The if-else (Transforming)\n", + "\n", + "Syntax\n", + "```py\n", + "new_list = [expression_if_true if condition else expression_if_false for item in iterable]\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "traditional way: ['Odd', 'Even', 'Odd', 'Even']\n", + "comprehension way: ['Odd', 'Even', 'Odd', 'Even']\n" + ] + } + ], + "source": [ + "numbers = [1, 2, 3, 4]\n", + "\n", + "# Traditional way\n", + "labels = []\n", + "\n", + "for n in numbers:\n", + " if n % 2 == 0:\n", + " labels.append(\"Even\")\n", + " else:\n", + " labels.append(\"Odd\")\n", + "\n", + "print(f\"traditional way: {labels}\")\n", + "\n", + "# Comprehension Way\n", + "c_labels = [\"Even\" if n % 2 == 0 else \"Odd\" for n in numbers]\n", + "print(f\"comprehension way: {c_labels}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> Evaluate \"Even\" if n % 2 == 0 else \"Odd\" for every n inside the loop. \\\n", + "> Note: it's just if-else comprehension first and then looping" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3. Matrix / Nested List Comprehensions" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "traditional way: [4, 5, 6]\n", + "traditional way: [4, 5, 6]\n" + ] + } + ], + "source": [ + "matrix = [[4, 5, 6]]\n", + "\n", + "# Traditional Way\n", + "flat = []\n", + "for row in matrix:\n", + " for num in row:\n", + " flat.append(num)\n", + "\n", + "\n", + "print(f\"traditional way: {flat}\")\n", + "\n", + "\n", + "# Comprehension way\n", + "flat = [num for row in matrix for num in row]\n", + "\n", + "print(f\"traditional way: {flat}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> How to read it: Read the loops from left to right, exactly like a sentence: \"Give me num for each row in matrix for each num in that row.\" \\\n", + "> OR, loop through matrix and get the row and loop through row " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.14.7)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/comprehensions/set/set.ipynb b/comprehensions/set/set.ipynb new file mode 100644 index 0000000..3156217 --- /dev/null +++ b/comprehensions/set/set.ipynb @@ -0,0 +1,124 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "28c0fb61", + "metadata": {}, + "source": [ + "# set comprehensions\n", + "\n", + "Syntax:\n", + "\n", + "```py\n", + "new_set = {expression for item in iterable}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "af590b52", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "a6071051", + "metadata": {}, + "source": [ + "## 1. Basic Set Comprehension (Removing Duplicates)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "6401979f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "traditional way: {'banana', 'cherry', 'apple'}\n", + "comprehension way: {'banana', 'cherry', 'apple'}\n" + ] + } + ], + "source": [ + "words = [\"Apple\", \"banana\", \"APPLE\", \"Banana\", \"cherry\"]\n", + "\n", + "# Traditional Way\n", + "unique_words = set()\n", + "for w in words:\n", + " unique_words.add(w.lower())\n", + "\n", + "print(f\"traditional way: {unique_words}\")\n", + "\n", + "# Comprehension way\n", + "unique_words = {w.lower() for w in words}\n", + "print(f\"comprehension way: {unique_words}\")" + ] + }, + { + "cell_type": "markdown", + "id": "47c765cb", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "035fc99e", + "metadata": {}, + "source": [ + "## 2. Set Comprehension with Filtering (if)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b94c5166", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'C', 'A'}\n" + ] + } + ], + "source": [ + "names = [\"Al\", \"Alice\", \"Bob\", \"Charlie\", \"Amanda\"]\n", + "\n", + "# extract first letter if length > 3\n", + "initials = {name[0] for name in names if len(name) > 3}\n", + "\n", + "print(initials)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.14.7)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/comprehensions/tuple/tuple.ipynb b/comprehensions/tuple/tuple.ipynb new file mode 100644 index 0000000..ff89324 --- /dev/null +++ b/comprehensions/tuple/tuple.ipynb @@ -0,0 +1,55 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fe39ccff", + "metadata": {}, + "source": [ + "> View [`Generator: The Tuple Expression`](../generator/generator.ipynb) for detail guide on tuple and generators." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "52457d4b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 4, 9, 16)\n" + ] + } + ], + "source": [ + "numbers: tuple = (1, 2, 3, 4)\n", + "\n", + "squared_nums: tuple = tuple(num**2 for num in numbers)\n", + "\n", + "print(squared_nums)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.14.7)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}