{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "21d3905f",
   "metadata": {},
   "source": [
    "# Aliasing and Copying"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8230d1b3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.285115Z",
     "iopub.status.busy": "2026-09-28T20:09:29.284719Z",
     "iopub.status.idle": "2026-09-28T20:09:29.664272Z",
     "shell.execute_reply": "2026-09-28T20:09:29.663834Z"
    },
    "tags": [
     "hide-input",
     "thebe-init"
    ]
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "# Find project root by looking for _config.yml\n",
    "current = Path.cwd()\n",
    "for parent in [current, *current.parents]:\n",
    "    if (parent / '_config.yml').exists():\n",
    "        project_root = parent\n",
    "        break\n",
    "else:\n",
    "    project_root = Path.cwd().parent.parent\n",
    "\n",
    "# Add project root to path\n",
    "sys.path.insert(0, str(project_root))\n",
    "\n",
    "# Import shared teaching helpers and cell magics\n",
    "from shared import thinkpython, diagram, jupyturtle, structshape\n",
    "from shared.download import download\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1dd51cc7",
   "metadata": {},
   "source": [
    "```{contents}\n",
    ":local:\n",
    ":depth: 2\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7bebd3df",
   "metadata": {},
   "source": [
    "A variable does not hold a list directly; it holds a reference to a list object. This section looks at what that means: when two names refer to the same object, how a change made through one name shows up through the other, and how to make copies that are truly independent.\n",
    "\n",
    "The examples use lists, but the same rules apply to every mutable collection, including sets, which you will meet in Section 7.4. Tuples, covered in Section 6.3, are immutable, so a change can never show up through an alias of a tuple itself.\n",
    "\n",
    "The table below summarizes the three cases:\n",
    "\n",
    "| Concept      | Outer Object | Inner Objects | Syntax                    | Changes affect original? |\n",
    "| ------------ | ------------ | ------------- | ------------------------- | ------------------------ |\n",
    "| Aliasing     | **Same**     | **Same**      | `b = a`                   | Yes                      |\n",
    "| Shallow Copy | **New**      | **Same**      | `[:]`, `copy()`, `list()` | Sometimes (when nested)  |\n",
    "| Deep Copy    | **New**      | **New**       | `copy.deepcopy()`         | No                       |\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9d27df5",
   "metadata": {},
   "source": [
    "## Objects and Values\n",
    "\n",
    "Consider these assignment statements:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-d9d27df5",
   "metadata": {},
   "source": [
    "```{index} identity operator (is), object identity\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "aa547282",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.666225Z",
     "iopub.status.busy": "2026-09-28T20:09:29.666089Z",
     "iopub.status.idle": "2026-09-28T20:09:29.667639Z",
     "shell.execute_reply": "2026-09-28T20:09:29.667364Z"
    }
   },
   "outputs": [],
   "source": [
    "a = 'banana'\n",
    "b = 'banana'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33d020aa",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "Both `a` and `b` refer to a string, but it is not obvious whether they refer to the *same* string. There are two possible states, shown in the following figure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "95a2aded",
   "metadata": {
    "editable": true,
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.668942Z",
     "iopub.status.busy": "2026-09-28T20:09:29.668885Z",
     "iopub.status.idle": "2026-09-28T20:09:29.670902Z",
     "shell.execute_reply": "2026-09-28T20:09:29.670530Z"
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [],
   "source": [
    "from shared.diagram import Bbox, Binding, Frame, Stack, Value, adjust, diagram\n",
    "\n",
    "s = 'banana'\n",
    "bindings = [Binding(Value(name), Value(repr(s))) for name in 'ab']\n",
    "frame1 = Frame(bindings, dy=-0.25)\n",
    "\n",
    "binding1 = Binding(Value('a'), Value(repr(s)), dy=-0.11)\n",
    "binding2 = Binding(Value('b'), draw_value=False, dy=0.11)\n",
    "frame2 = Frame([binding1, binding2], dy=-0.25)\n",
    "\n",
    "stack = Stack([frame1, frame2], dx=1.7, dy=0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3d75a28c",
   "metadata": {
    "editable": true,
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.671897Z",
     "iopub.status.busy": "2026-09-28T20:09:29.671831Z",
     "iopub.status.idle": "2026-09-28T20:09:29.721721Z",
     "shell.execute_reply": "2026-09-28T20:09:29.721336Z"
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 285x76 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "width, height, x, y = [2.85, 0.76, 0.17, 0.51]\n",
    "ax = diagram(width, height)\n",
    "bbox = stack.draw(ax, x, y)\n",
    "# adjust(x, y, bbox)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f0b0431",
   "metadata": {},
   "source": [
    "In the diagram on the left, `a` and `b` refer to two different objects that have the\n",
    "same value. In the diagram on the right, they refer to the same object.\n",
    "To check whether two variables refer to the same object, you can use the `is` operator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a37e37bf",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.722881Z",
     "iopub.status.busy": "2026-09-28T20:09:29.722803Z",
     "iopub.status.idle": "2026-09-28T20:09:29.724897Z",
     "shell.execute_reply": "2026-09-28T20:09:29.724539Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 'banana'\n",
    "b = 'banana'\n",
    "a is b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1eb0e36",
   "metadata": {},
   "source": [
    "In this example, Python only created one string object, and both `a`\n",
    "and `b` refer to it.\n",
    "Python sometimes reuses one object for identical short strings, an optimization called *interning*, so `a is b` happens to be `True` here. Don't rely on it: use `==` to compare values and `is` only to check whether two names refer to the same object.\n",
    "\n",
    "But when you create two lists, you get two objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "d6af7316",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.725850Z",
     "iopub.status.busy": "2026-09-28T20:09:29.725785Z",
     "iopub.status.idle": "2026-09-28T20:09:29.727660Z",
     "shell.execute_reply": "2026-09-28T20:09:29.727307Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [1, 2, 3]\n",
    "b = [1, 2, 3]\n",
    "a is b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8d4c3d4",
   "metadata": {},
   "source": [
    "So the state diagram looks like this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "dea08b82",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.728561Z",
     "iopub.status.busy": "2026-09-28T20:09:29.728507Z",
     "iopub.status.idle": "2026-09-28T20:09:29.730095Z",
     "shell.execute_reply": "2026-09-28T20:09:29.729712Z"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [],
   "source": [
    "t = [1, 2, 3]\n",
    "binding1 = Binding(Value('a'), Value(repr(t)))\n",
    "binding2 = Binding(Value('b'), Value(repr(t)))\n",
    "frame = Frame([binding1, binding2], dy=-0.25)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7e66ee69",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.730992Z",
     "iopub.status.busy": "2026-09-28T20:09:29.730932Z",
     "iopub.status.idle": "2026-09-28T20:09:29.749482Z",
     "shell.execute_reply": "2026-09-28T20:09:29.749062Z"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAIgAAABgCAYAAADGrTq9AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAABQdJREFUeJzt3EkobXEcB/CfKTJcHuHVXaCQpJeQedgoNkToEWUhC6VkTAorGVaEWL0oJbKShSELr2fMs7AQXTLkGrIwZZ5e/39ZvFy/e6/cAd9PnQznnM6953zP//yOe34snp6engjgFZavzQBAQEArjCDAQkCAhYAACwEBFgICLAQEWAgIsBAQYCEgwEJAgIWAAAsBARYCAiwEBFgICLAQEGAhIMCypjc6Pz9/66pgYk5OTjovixEEWAgIsBAQYCEgwEJAgIWAAAsBARYCAiwEBFgICLAQEC0UCgVFRkbS2NiY/Pnv37+UmJhInp6elJOTQ7oaGhqimJgYioiIkFN7e7tO683Pz8v1xBQeHk4lJSV0c3Mj583MzMjfi9d4cnJChmDx1v8Pou9nMQUFBbS+vk63t7ekVCqps7NT7mRT2Nrakjs3ODiYAgICyNLy9fNEoVDQzs4Oubi4yJ/VajXt7+/T8vIyTUxMUH9/v07bnJubIx8fH/meT09PKT4+njo6OiguLo5d7/LykmxsbOT0+PhIeXl5FB0dTcXFxa++xg/5WUxzczNNTU3R7OysfIONjY1kKu7u7uTg4ECjo6PU29tLKysrcufrQqlUUlhYGNna2uq1TTEKPZ8Qzs7O5O/vLw+qNvb29jIcgji5rq6uyMLCgsz+01x9DQ4O0sDAAF1fX8vJzc3txTILCwu0t7dnrJckD/bx8bEMyuTkJGVlZdH3798Nvt3V1VX5XltbW3Vafnt7W17ONjc3KSkpiQoLC8lYjDKCiFGju7tbXofFNVWMHs/X0a9GrVZTdna2DIcIqC68vLzkJVGlUsn9Njw8TJ9qBBEFlLjuubq6ymHy169fGpcTRZgxXFxcyPpBHKxv377JekBbLfIeRO2SmppKlZWVlJ6ervf6jo6OlJGRIUfjzMxM+jQjiKj6/fz8KCQkRA6RP378IFM6OjqSxV9ycjLl5+dTYGDgu4RjcXGRUlJSNM47ODiQ80pLSyk3N/e/eeKyGhoaqnG9jY0Nuru7k9+Lk2tkZISCgoLoU40gosjq6en573d1dXVkKt7e3nJ6C5VKJQ+0CJiopcTIU15eLusCUXTa2dlpXK+hoYF2d3epq6tLTkJRUZG8KxEBsbbWfCh+//4tL89WVlZ0f39PCQkJVFVVRcZitNvcj0qhxy1kWVmZLHSjoqL02kZbW5u8wxG1iaFfo763uQiIFr6+vuTh4UH19fXy8mhOROEq6pnDw0NaWlqSQdEFAgIf7w9l8DEhIMBCQICFgAALAQEWAgIsBARYCAiwEBBgISDAQkCAhYAACwEB0wfEkH0bYFgYQbRQoHHK8E+UiZ1cUVFB4+Pj8oHh6upq+vnzJ5kKGqeczK8vRjT7/PnzR/Z2iOcqRSOReJzf1I1Tog1DtELq+lS7UqmU09raml7bFO/3mb6NU88+deOUeHpcEO2Hop90enr6RUDQOPVFG6c0MeZZYE7UaJzSrK+vj2pqauTZIB62bWpqerEMGqe+aOOU8PDwQLGxsZSWlkYtLS0mqz8ENE6ZWQ1ydnYmv9bW1pI5QOOU7tAXo4UCjVPorOP4onEKAflqnNA4Be8Fn8UACwEBFgICLAQEWAgIsBAQYCEgYJg/tcPXgBEEWAgIsBAQYCEgwEJAgIWAAAsBARYCAiwEBFgICLAQEGAhIMBCQICFgAALAQEWAgIsBARYCAiwEBBgISBAnH9XF5b1n3vZ8wAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 116x76 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "width, height, x, y = [1.16, 0.76, 0.21, 0.51]\n",
    "ax = diagram(width, height)\n",
    "bbox = frame.draw(ax, x, y)\n",
    "# adjust(x, y, bbox)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc115a9f",
   "metadata": {},
   "source": [
    "In this case, the two lists are **equivalent**, because they have the same elements, but not **identical**, because they are not the same object. \n",
    "If two objects are identical, they are also equivalent, but if they are equivalent, they are not necessarily identical.\n",
    "The `is` operator checks **identity**, whether two names refer to the same object, while `==` checks only whether the values are equivalent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d0f49fa5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.750629Z",
     "iopub.status.busy": "2026-09-28T20:09:29.750567Z",
     "iopub.status.idle": "2026-09-28T20:09:29.752143Z",
     "shell.execute_reply": "2026-09-28T20:09:29.751865Z"
    },
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Objects and Values *(basic)*\n",
    "x = [10, 20, 30]\n",
    "y = x\n",
    "z = [10, 20, 30]\n",
    "# 1. Check if x and y refer to the same object using \"is\"\n",
    "# 2. Check if x and z have the same value using \"==\"\n",
    "# 3. Check if x and z refer to the same object using \"is\"\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ed132eb8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.753012Z",
     "iopub.status.busy": "2026-09-28T20:09:29.752950Z",
     "iopub.status.idle": "2026-09-28T20:09:29.754826Z",
     "shell.execute_reply": "2026-09-28T20:09:29.754439Z"
    },
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x is y: True\n",
      "x == z: True\n",
      "x is z: False\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "x = [10, 20, 30]\n",
    "y = x\n",
    "z = [10, 20, 30]\n",
    "\n",
    "same_object_xy = x is y\n",
    "same_value_xz = x == z\n",
    "same_object_xz = x is z\n",
    "\n",
    "print(f\"x is y: {same_object_xy}\")  # True - same object (alias)\n",
    "print(f\"x == z: {same_value_xz}\")   # True - same value (equivalent)\n",
    "print(f\"x is z: {same_object_xz}\")  # False - different objects"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a58db021",
   "metadata": {},
   "source": [
    "## Aliasing\n",
    "\n",
    "Aliasing occurs when two or more variables point to the same object in memory. When you do a **variable assignment** using `=` in Python, you're not **copying** the object; you're creating another variable that points to the **same object**. This second variable is an **alias**.\n",
    "\n",
    "If `a` refers to an object and you assign `b = a`, then both variables refer to the same object."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-a58db021",
   "metadata": {},
   "source": [
    "```{index} aliasing, reference\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "d6a7eb5b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.755801Z",
     "iopub.status.busy": "2026-09-28T20:09:29.755731Z",
     "iopub.status.idle": "2026-09-28T20:09:29.757733Z",
     "shell.execute_reply": "2026-09-28T20:09:29.757372Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [1, 2, 3]\n",
    "b = a\n",
    "b is a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6ab3262",
   "metadata": {},
   "source": [
    "So the state diagram looks like this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "dd406791",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.758663Z",
     "iopub.status.busy": "2026-09-28T20:09:29.758600Z",
     "iopub.status.idle": "2026-09-28T20:09:29.760216Z",
     "shell.execute_reply": "2026-09-28T20:09:29.759894Z"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [],
   "source": [
    "t = [1, 2, 3]\n",
    "binding1 = Binding(Value('a'), Value(repr(t)), dy=-0.11)\n",
    "binding2 = Binding(Value('b'), draw_value=False, dy=0.11)\n",
    "frame = Frame([binding1, binding2], dy=-0.25)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "552e1e1e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.761118Z",
     "iopub.status.busy": "2026-09-28T20:09:29.761042Z",
     "iopub.status.idle": "2026-09-28T20:09:29.779757Z",
     "shell.execute_reply": "2026-09-28T20:09:29.779357Z"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 111x81 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "width, height, x, y = [1.11, 0.81, 0.17, 0.56]\n",
    "ax = diagram(width, height)\n",
    "bbox = frame.draw(ax, x, y)\n",
    "# adjust(x, y, bbox)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c676fde9",
   "metadata": {},
   "source": [
    "The association of a variable with an object is called a **reference**. In this example, there are two references to the same object.\n",
    "\n",
    "An object with more than one reference has more than one name, so the object is **aliased**. If the aliased object is mutable, a change made through one name is visible through the other. In this example, changing the list through `b` also changes what you see through `a`, because both names refer to the same list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "6e3c1b24",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.780822Z",
     "iopub.status.busy": "2026-09-28T20:09:29.780751Z",
     "iopub.status.idle": "2026-09-28T20:09:29.782694Z",
     "shell.execute_reply": "2026-09-28T20:09:29.782401Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 2, 3]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[0] = 5\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3ef0537",
   "metadata": {},
   "source": [
    "In other words, `a` \"sees\" the change. This behavior can be useful, but it is error-prone. In general, avoid aliasing mutable objects unless you intend to share them."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d55a743",
   "metadata": {},
   "source": [
    "You can confirm that two names share one object with `is`, or by comparing their `id()` values, which identify an object while it exists:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "59ba7aa8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.783711Z",
     "iopub.status.busy": "2026-09-28T20:09:29.783655Z",
     "iopub.status.idle": "2026-09-28T20:09:29.785515Z",
     "shell.execute_reply": "2026-09-28T20:09:29.785160Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original:\t [999, 2, 3, 4, 5]\n",
      "Alias:\t\t [999, 2, 3, 4, 5]\n",
      "Same id?\t True\n",
      "Same object?\t True\n"
     ]
    }
   ],
   "source": [
    "# Aliasing: both variables point to the same list\n",
    "original = [1, 2, 3, 4, 5]\n",
    "alias = original    # NOT a copy!\n",
    "\n",
    "alias[0] = 999      # Modify through the alias\n",
    "\n",
    "print(\"Original:\\t\", original)  # check to see if original is modified\n",
    "print(\"Alias:\\t\\t\", alias)        \n",
    "\n",
    "print(\"Same id?\\t\", id(original) == id(alias))  # True\n",
    "\n",
    "print(\"Same object?\\t\", original is alias)  # True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b09dcca3",
   "metadata": {},
   "source": [
    "For immutable objects like strings, aliasing is not as much of a problem.\n",
    "In this example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "dad8a246",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.786489Z",
     "iopub.status.busy": "2026-09-28T20:09:29.786428Z",
     "iopub.status.idle": "2026-09-28T20:09:29.787776Z",
     "shell.execute_reply": "2026-09-28T20:09:29.787460Z"
    }
   },
   "outputs": [],
   "source": [
    "c = 'banana'\n",
    "d = 'banana'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "952bbf60",
   "metadata": {},
   "source": [
    "It almost never makes a difference whether `c` and `d` refer to the same\n",
    "string or not."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48707a9d",
   "metadata": {},
   "source": [
    "Reassigning a name is different from modifying an object. With immutable strings, reassigning one name creates a new object and never affects the other name:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "79650416",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.788701Z",
     "iopub.status.busy": "2026-09-28T20:09:29.788649Z",
     "iopub.status.idle": "2026-09-28T20:09:29.790273Z",
     "shell.execute_reply": "2026-09-28T20:09:29.790001Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Same object? True\n",
      "Chen Alice\n",
      "Same object? False\n"
     ]
    }
   ],
   "source": [
    "# Contrast with immutable strings\n",
    "name1 = \"Chen\"\n",
    "name2 = name1                         # alias: both names refer to the same string\n",
    "print(\"Same object?\", name1 is name2)  # True\n",
    "\n",
    "name2 = \"Alice\"                       # reassignment: name2 now refers to a new string\n",
    "print(name1, name2)                   # name1 is unchanged\n",
    "print(\"Same object?\", name1 is name2)  # False"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2816d85",
   "metadata": {},
   "source": [
    "Aliasing is useful for efficiency (no copying needed), but can cause unexpected behavior if you modify mutable objects, thinking you have independent copies."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "45f181b7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.791319Z",
     "iopub.status.busy": "2026-09-28T20:09:29.791246Z",
     "iopub.status.idle": "2026-09-28T20:09:29.792708Z",
     "shell.execute_reply": "2026-09-28T20:09:29.792408Z"
    },
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Aliasing *(applied)*\n",
    "a = [1, 2, 3]\n",
    "# 1. Create an alias b that points to the same list as a\n",
    "# 2. Modify the list through b by changing the first element to 99\n",
    "# 3. Create a true copy c using slicing\n",
    "# 4. Modify c and observe that a remains unchanged\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "1085deea",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.793567Z",
     "iopub.status.busy": "2026-09-28T20:09:29.793507Z",
     "iopub.status.idle": "2026-09-28T20:09:29.795281Z",
     "shell.execute_reply": "2026-09-28T20:09:29.795055Z"
    },
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a after aliasing: [99, 2, 3]\n",
      "b: [99, 2, 3]\n",
      "Same object? True\n",
      "\n",
      "a after copying: [99, 2, 3]\n",
      "c: [99, 777, 3]\n",
      "Same object? False\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "a = [1, 2, 3]\n",
    "b = a  # alias\n",
    "b[0] = 99\n",
    "\n",
    "print(f\"a after aliasing: {a}\")\n",
    "print(f\"b: {b}\")\n",
    "print(f\"Same object? {a is b}\")\n",
    "\n",
    "c = a[:]  # true copy\n",
    "c[1] = 777\n",
    "\n",
    "print(f\"\\na after copying: {a}\")\n",
    "print(f\"c: {c}\")\n",
    "print(f\"Same object? {a is c}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35045bef",
   "metadata": {},
   "source": [
    "## List Arguments in Functions\n",
    "\n",
    "When you pass a list to a function, the function gets a reference to the\n",
    "list. If the function modifies the list, the caller sees the change. For\n",
    "example, `pop_first` uses the list method `pop` to remove the first element from a list."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-35045bef",
   "metadata": {},
   "source": [
    "```{index} list argument, aliasing\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "613b1845",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.796292Z",
     "iopub.status.busy": "2026-09-28T20:09:29.796238Z",
     "iopub.status.idle": "2026-09-28T20:09:29.797689Z",
     "shell.execute_reply": "2026-09-28T20:09:29.797323Z"
    }
   },
   "outputs": [],
   "source": [
    "def pop_first(lst):\n",
    "    return lst.pop(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4953b0f9",
   "metadata": {},
   "source": [
    "Here is how to use it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "3aff3598",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.798642Z",
     "iopub.status.busy": "2026-09-28T20:09:29.798587Z",
     "iopub.status.idle": "2026-09-28T20:09:29.800255Z",
     "shell.execute_reply": "2026-09-28T20:09:29.799983Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'a'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "letters = ['a', 'b', 'c']\n",
    "pop_first(letters)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef5d3c1e",
   "metadata": {},
   "source": [
    "The return value is the first element, which has been removed from the list, as displaying the list shows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "c10e4dcc",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.801082Z",
     "iopub.status.busy": "2026-09-28T20:09:29.801028Z",
     "iopub.status.idle": "2026-09-28T20:09:29.802684Z",
     "shell.execute_reply": "2026-09-28T20:09:29.802401Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['b', 'c']"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "letters"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5288e08",
   "metadata": {},
   "source": [
    "In this example, the parameter `lst` and the variable `letters` are aliases for the same object, so the state diagram looks like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "a13e72c7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.803536Z",
     "iopub.status.busy": "2026-09-28T20:09:29.803484Z",
     "iopub.status.idle": "2026-09-28T20:09:29.805289Z",
     "shell.execute_reply": "2026-09-28T20:09:29.805006Z"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [],
   "source": [
    "from shared.diagram import make_list, Binding, Value\n",
    "\n",
    "lst = make_list('abc', dy=-0.3, offsetx=0.1)\n",
    "binding1 = Binding(Value('letters'), draw_value=False)\n",
    "frame1 = Frame([binding1], name='__main__', loc='left')\n",
    "\n",
    "binding2 = Binding(Value('lst'), draw_value=False, dx=0.61, dy=0.35)\n",
    "frame2 = Frame([binding2], name='pop_first', loc='left', offsetx=0.08)\n",
    "\n",
    "stack = Stack([frame1, frame2], dx=-0.3, dy=-0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ac62b394",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.806176Z",
     "iopub.status.busy": "2026-09-28T20:09:29.806115Z",
     "iopub.status.idle": "2026-09-28T20:09:29.832185Z",
     "shell.execute_reply": "2026-09-28T20:09:29.831769Z"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOAAAACQCAYAAAARD2cgAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAADtVJREFUeJztnQuwVeMbxt9ujlCuuauIEqVIQ+4kIpcoROSayWVIZaZxq2lMY5gxhHGbiImEIUYuSUIlYVxSklsRuauOS4X6z++d/zpzOu1zzj5nr3W+tfZ+fjN79j7n7LP32muv5/ve7/ve9/karV+/fr0JIYLQOMzbCiEkQCECox5QiIBIgEIERAIUIiASoBABkQCFCIgEKERAJEAhAiIBChEQCVCIgEiAQgREAhQiIBKgEAGRAIUIiAQoREAkQCECIgEKERAJUIiASIBCBEQCFCIgEqBIBY0aNbIVK1b44xNPPNE+++yzGp8/evRoW716tWWdRrIlFGkR4O+//25bbbVVIs9PK+oBRepo27atffjhh/745ptvto4dO1rXrl39tnTpUhsyZIj/7fDDD/ff/fTTT5ZV1AOKVNCoUo+GAKdMmWJt2rSx3Xff3ZYvX27Nmze3v/76yxo3bmybbrqpekAhkqZly5a211572bnnnmv333+//fbbby6+YkIhqEgtTZo0sblz59rQoUM9zDz44IPtrbfesmKiaegDEKI6ysvL/cZYj9uCBQvsgw8+8MctWrSwlStXZn4SRgIUqWXlypXWv39/+/PPP33MRzh6/vnn+9+GDx9uvXr1ss0228ymTZtm22+/vWURTcIIERCNAYUIiAQoREAkQCECokmYGmAGrphhJjENlBfpec7n/KoHFCIgEqAQAZEAhQiIBChEQCRAIQIiAQoREAlQiIBIgEIERAIUIiCpFyCeH2nPlKByO3L0qomxY8du4OT1wgsv2Lx58xI+OlEbnTp1iuU5RSlAzHnSkjJVKLfccstGAnz33Xfr9Vr//feflSpvvvmmTZ482V566aXMn4fEBHjUUUd50eQRRxxhrVu3thtvvNFefPFFO+yww9x05/bbb6947ogRI6x79+7e2/H8yp6Qlf0i+b+bbrrJevTo4WY9OGaljS+++MKLSI888kg/TrxMAFsF6N27tx166KH2+OOP+/kYN26c//zII4/43ydNmmRHH320V33z3Pnz5/vvH3vsMevTp4/7o2DN8N5779mtt95qBx54oP8/t2+++SbgJzd74okn7Pnnn3dzpaT4+eef7Y8//rCzzjrLttlmG/v8888Lfs1tt93W76+//nr/3jiXnPvKrx09JzMFuQhwu+2285Zq1apVLp7zzjvP7rrrLvv++++tQ4cOtmzZMrcU4KS2atWq4kucMGGCvfzyyzndsk455RS/aH/55Rdr166dLVy40HbZZZckPkLeoS8hKBc/PfUxxxxjDz74oLVv395dvHr27Gl33323devWreJ5kY0C9nqdO3e2K664wn/G/+S2225zcZaVldmcOXNcuISpCHDYsGE2a9YsrwznnOy33362ePHijRzD8iXuyIJoZfr06fb3339bly5dvBHZeuuta/2/8joMMT766CNr1qyZ7bPPPvbjjz/aJ5984uc4DrimuGbh6aef9nP+7LPP1vv18jm/iVZD0BNgrMOXsMcee9hJJ53kgkIwCG7JkiXe67366qsuTL6IdevWuftVdZxzzjl+z4niNb/++uvEBFhXaDE//fRTu/DCCyt+R2u9aNEiF2BtTJ061S8oRByB0Lig4aCDDnLxAWLm8w8ePNiff/zxx+c8D/w/Rkac16o0bRr/17/TTju5lcTHH3/s/i0cb/SdxcHq1att880398ebbLJJrO7YM2bM8IiF74zzlWRP3iACrNwaI8SqP//777/eI1x55ZU+FqJH44sjDM33NXmNtEAwQWMze/bsev8/F+uoUaNy/j268KLPzgXzzjvvuMDoBR566CE75JBDrJgpKyuztWvX+mPu47Ip/Pbbb30oNHPmTG/YaAhPOOEEK/p6QFpLQgpaTi5AwrWsQmtP2DFx4kQfq8GXX37pomS8wt8Ix6MQNPo5gj0RLrnkErvoootst91281aYsO6AAw7Y6L2IFmipERw3el7Cs6oC5L0J2xsiBKXHe+211+ocgtaFnXfe2d5//30PQYmg4op++B64DnfccUe/Dh944AFrCIILkDHQgAEDbN999/WBbt++fS2rENI9+eSTNnLkSLvnnnt8ho7PNH78eP87Pf2pp57qTl44P/O5L7vsMg89CSVx/BozZowNHDjQe3ZaeELLXALkgmFMzdiPsJ7oIc5Qrz4wecbYNwnhReB+xvljboEGhEmoOOD669evn4f5NJZMeDUEckWrgbSv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",
      "text/plain": [
       "<Figure size 204x124 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "width, height, x, y = [2.04, 1.24, 1.06, 0.85]\n",
    "ax = diagram(width, height)\n",
    "bbox1 = stack.draw(ax, x, y)\n",
    "bbox2 = lst.draw(ax, x+0.5, y)\n",
    "bbox = Bbox.union([bbox1, bbox2])\n",
    "# adjust(x, y, bbox)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b3b07c9",
   "metadata": {},
   "source": [
    "Passing a reference to an object as an argument to a function creates a form of aliasing.\n",
    "If the function modifies the object, those changes persist after the function is done."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "0c5b37ad",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.833286Z",
     "iopub.status.busy": "2026-09-28T20:09:29.833223Z",
     "iopub.status.idle": "2026-09-28T20:09:29.834941Z",
     "shell.execute_reply": "2026-09-28T20:09:29.834609Z"
    },
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: List Arguments in Functions *(applied)*\n",
    "def add_item(lst, item):\n",
    "    \"\"\"Add item to list and return the list\"\"\"\n",
    "    lst.append(item)\n",
    "    return lst\n",
    "\n",
    "# 1. Create a list with [1, 2, 3], call it original\n",
    "# 2. Call add_item with your list and the value 4, \n",
    "#    save the result in a variable called updated\n",
    "# 3. Print the original list to see if it changed after calling the function\n",
    "# 4. check if original and updated refer to the same object using \"is\"\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "f2c291b0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.835795Z",
     "iopub.status.busy": "2026-09-28T20:09:29.835740Z",
     "iopub.status.idle": "2026-09-28T20:09:29.837525Z",
     "shell.execute_reply": "2026-09-28T20:09:29.837218Z"
    },
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original list: [1, 2, 3]\n",
      "Returned list: [1, 2, 3, 4]\n",
      "Original list after function call: [1, 2, 3, 4]\n",
      "Same object? True\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "def add_item(lst, item):\n",
    "    \"\"\"Add item to list and return the list\"\"\"\n",
    "    lst.append(item)\n",
    "    return lst\n",
    "\n",
    "original = [1, 2, 3]\n",
    "print(f\"Original list: {original}\")\n",
    "\n",
    "updated = add_item(original, 4)\n",
    "print(f\"Returned list: {updated}\")\n",
    "print(f\"Original list after function call: {original}\")\n",
    "print(f\"Same object? {updated is original}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47259663",
   "metadata": {},
   "source": [
    "## Shallow Copy\n",
    "\n",
    "You can make a shallow copy of a list in four ways: slicing with `[:]`, the `.copy()` method, the `list()` function, or `copy.copy()` from the `copy` module."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-47259663",
   "metadata": {},
   "source": [
    "```{index} shallow copy, list.copy(), copy.copy()\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "0084ced0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.838490Z",
     "iopub.status.busy": "2026-09-28T20:09:29.838434Z",
     "iopub.status.idle": "2026-09-28T20:09:29.839957Z",
     "shell.execute_reply": "2026-09-28T20:09:29.839646Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "a = [1, 2, 3]\n",
    "\n",
    "b = a[:]          # list slicing\n",
    "b = a.copy()      # copy() method\n",
    "b = list(a)       # list() function\n",
    "b = copy.copy(a)  # copy module"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b7bf643",
   "metadata": {},
   "source": [
    "Each of these creates a new list object, but only the top level is copied. If the list contains mutable objects such as nested lists, the copy holds references to the same inner objects rather than copies of them.\n",
    "\n",
    "For a **flat list** that holds only immutable values, such as numbers, strings, or Booleans, a shallow copy is all you need: each copy is a new list object, as the `is` checks below show."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "5509ba45",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.840958Z",
     "iopub.status.busy": "2026-09-28T20:09:29.840887Z",
     "iopub.status.idle": "2026-09-28T20:09:29.842975Z",
     "shell.execute_reply": "2026-09-28T20:09:29.842668Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'b', 'c', 'd']\n",
      "['a', 'b', 'c', 'd']\n",
      "['a', 'b', 'c', 'd']\n",
      "['a', 'b', 'c', 'd']\n",
      "All copies have the same contents? True\n",
      "letters_copy1 is letters? False\n",
      "letters_copy2 is letters? False\n",
      "letters_copy3 is letters? False\n",
      "letters_copy4 is letters? False\n"
     ]
    }
   ],
   "source": [
    "# four ways to create a shallow copy\n",
    "import copy\n",
    "\n",
    "letters = ['a', 'b', 'c', 'd']\n",
    "\n",
    "letters_copy1 = letters[:]          # list slicing\n",
    "letters_copy2 = letters.copy()      # the copy() method\n",
    "letters_copy3 = list(letters)       # the list function\n",
    "letters_copy4 = copy.copy(letters)  # using the copy module\n",
    "\n",
    "print(letters_copy1)\n",
    "print(letters_copy2)\n",
    "print(letters_copy3)\n",
    "print(letters_copy4)\n",
    "\n",
    "print(\"All copies have the same contents?\", letters_copy1 == letters_copy2 == letters_copy3 == letters_copy4)  # True, contents are the same\n",
    "print(\"letters_copy1 is letters?\", letters_copy1 is letters)  # False, different objects in memory\n",
    "print(\"letters_copy2 is letters?\", letters_copy2 is letters)  # False, different objects in memory\n",
    "print(\"letters_copy3 is letters?\", letters_copy3 is letters)  # False, different objects in memory\n",
    "print(\"letters_copy4 is letters?\", letters_copy4 is letters)  # False, different objects in memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "a95c3cea",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.843872Z",
     "iopub.status.busy": "2026-09-28T20:09:29.843811Z",
     "iopub.status.idle": "2026-09-28T20:09:29.845659Z",
     "shell.execute_reply": "2026-09-28T20:09:29.845389Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Same value?\t True\n",
      "Same object?\t False\n",
      "update shallow:\t [1, 2, 3, 4, 999]\n",
      "Original:\t [1, 2, 3, 4, 5]\n",
      "Shallow:\t [1, 2, 3, 4, 999]\n"
     ]
    }
   ],
   "source": [
    "# a simpler example: changing a shallow copy of a flat list\n",
    "original = [1, 2, 3, 4, 5]\n",
    "shallow = original[:]  # Creates a new list\n",
    "\n",
    "print(\"Same value?\\t\", original == shallow)   # True\n",
    "print(\"Same object?\\t\", original is shallow)  # False\n",
    "\n",
    "# Modify the shallow copy\n",
    "shallow[4] = 999\n",
    "print(\"update shallow:\\t\", shallow)\n",
    "\n",
    "print(\"Original:\\t\", original)  # Original is unchanged\n",
    "print(\"Shallow:\\t\", shallow)    # Only the copy is modified\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fb75f91",
   "metadata": {},
   "source": [
    "However, for nested lists (lists containing other lists), shallow copy shares references to the nested objects:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "8a1cdeaa",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.846612Z",
     "iopub.status.busy": "2026-09-28T20:09:29.846556Z",
     "iopub.status.idle": "2026-09-28T20:09:29.848499Z",
     "shell.execute_reply": "2026-09-28T20:09:29.848178Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original-shallow same value?\t True\n",
      "original-shallow same object?\t False\n",
      "update shallow (99):\t\t [[1, 2, 99], [3, 4]]\n",
      "is original updated?\t\t [[1, 2, 99], [3, 4]]\n",
      "same nested object?\t\t True\n"
     ]
    }
   ],
   "source": [
    "# Using copy.copy() with nested lists\n",
    "import copy\n",
    "original = [[1, 2], [3, 4]]\n",
    "shallow = copy.copy(original)\n",
    "\n",
    "print(\"original-shallow same value?\\t\", original == shallow)   # True - contents are the same\n",
    "print(\"original-shallow same object?\\t\", id(original) == id(shallow))  # False - different list objects\n",
    "\n",
    "shallow[0].append(99)\n",
    "print(\"update shallow (99):\\t\\t\", shallow)\n",
    "print(\"is original updated?\\t\\t\", original)  # [[1, 2, 99], [3, 4]] - nested list affected!\n",
    "\n",
    "print(\"same nested object?\\t\\t\", shallow[0] is original[0])  # True - same nested list object"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd8342d4",
   "metadata": {},
   "source": [
    "The two outer lists are different objects, but they share the same inner lists, so a change to `shallow[0]` also shows up in `original[0]`. The same thing happens when you make a shallow copy with slicing:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "f4a9d602",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.849577Z",
     "iopub.status.busy": "2026-09-28T20:09:29.849519Z",
     "iopub.status.idle": "2026-09-28T20:09:29.851259Z",
     "shell.execute_reply": "2026-09-28T20:09:29.850917Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original: [[999, 2, 3], [4, 5, 6]]\n",
      "Shallow: [[999, 2, 3], [4, 5, 6]]\n",
      "Same nested object? True\n"
     ]
    }
   ],
   "source": [
    "# Using slicing with nested lists\n",
    "original = [[1, 2, 3], [4, 5, 6]]\n",
    "shallow = original[:]  # or original.copy()\n",
    "\n",
    "# Modify the nested list\n",
    "shallow[0][0] = 999\n",
    "\n",
    "print(\"Original:\", original)  # Original is also modified!\n",
    "print(\"Shallow:\", shallow)\n",
    "print(\"Same nested object?\", shallow[0] is original[0])  # True - same nested list object"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d09c783a",
   "metadata": {},
   "source": [
    "As you can see, modifying the nested list in `shallow` also affects `original` because they share references to the same inner lists."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5db2e698",
   "metadata": {},
   "source": [
    "## Deep Copy\n",
    "\n",
    "To make a **deep copy**, use `deepcopy()` from the `copy` module. It copies the outer list and, recursively, every object nested inside it, so the copy is completely independent of the original."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-5db2e698",
   "metadata": {},
   "source": [
    "```{index} deep copy, copy.deepcopy()\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "6167935c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.852153Z",
     "iopub.status.busy": "2026-09-28T20:09:29.852098Z",
     "iopub.status.idle": "2026-09-28T20:09:29.853967Z",
     "shell.execute_reply": "2026-09-28T20:09:29.853627Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original: [[1, 2, 3], [4, 5, 6]]\n",
      "Deep copy: [[1, 2, 3], [4, 5, 6]]\n",
      "original-deep same value? True\n",
      "original-deep same object? False\n",
      "same nested object? False\n",
      "Original: [[1, 2, 3], [4, 5, 6]]\n",
      "Deep copy: [[999, 2, 3], [4, 5, 6]]\n"
     ]
    }
   ],
   "source": [
    "import copy\n",
    "\n",
    "original = [[1, 2, 3], [4, 5, 6]]\n",
    "deep = copy.deepcopy(original)\n",
    "\n",
    "print(\"Original:\", original)  # Original is unchanged\n",
    "print(\"Deep copy:\", deep)    # Only the deep copy is modified\n",
    "\n",
    "print(\"original-deep same value?\", original == deep)   # True - contents are the same\n",
    "print(\"original-deep same object?\", id(original) == id(deep))  # False - different list objects\n",
    "print(\"same nested object?\", deep[0] is original[0])  # False - different nested list objects\n",
    "\n",
    "# Modify the nested list\n",
    "deep[0][0] = 999\n",
    "\n",
    "print(\"Original:\", original)  # Original is unchanged\n",
    "print(\"Deep copy:\", deep)    # Only the deep copy is modified"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "e182a1b0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.854832Z",
     "iopub.status.busy": "2026-09-28T20:09:29.854779Z",
     "iopub.status.idle": "2026-09-28T20:09:29.856379Z",
     "shell.execute_reply": "2026-09-28T20:09:29.856108Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "[[1, 2], [3, 4]]\n",
      "[[1, 2, 99], [3, 4]]\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "# simpler example with deep copy\n",
    "import copy\n",
    "original = [[1, 2], [3, 4]]\n",
    "deep = copy.deepcopy(original)\n",
    "\n",
    "print(original is deep)          # False - different outer lists\n",
    "\n",
    "deep[0].append(99)\n",
    "print(original)  # [[1, 2], [3, 4]] - original unchanged!\n",
    "print(deep)      # [[1, 2, 99], [3, 4]] - only deep copy changed\n",
    "print(deep[0] is original[0])    # False - different nested list objects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "b0654c62",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.857278Z",
     "iopub.status.busy": "2026-09-28T20:09:29.857207Z",
     "iopub.status.idle": "2026-09-28T20:09:29.858818Z",
     "shell.execute_reply": "2026-09-28T20:09:29.858479Z"
    },
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Shallow vs. Deep Copy *(applied)*\n",
    "import copy\n",
    "teams = [['Ann', 'Bo'], ['Cy', 'Di']]\n",
    "# 1. Make a shallow copy of teams called shallow and a deep copy called deep\n",
    "# 2. Append 'Ed' to the first team in shallow\n",
    "# 3. Append 'Fay' to the first team in deep\n",
    "# 4. Print teams, shallow, and deep.\n",
    "#    Which change shows up in teams, and why?\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "4532fae8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-28T20:09:29.859686Z",
     "iopub.status.busy": "2026-09-28T20:09:29.859630Z",
     "iopub.status.idle": "2026-09-28T20:09:29.861495Z",
     "shell.execute_reply": "2026-09-28T20:09:29.861213Z"
    },
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "teams:   [['Ann', 'Bo', 'Ed'], ['Cy', 'Di']]\n",
      "shallow: [['Ann', 'Bo', 'Ed'], ['Cy', 'Di']]\n",
      "deep:    [['Ann', 'Bo', 'Fay'], ['Cy', 'Di']]\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "import copy\n",
    "teams = [['Ann', 'Bo'], ['Cy', 'Di']]\n",
    "\n",
    "shallow = teams.copy()\n",
    "deep = copy.deepcopy(teams)\n",
    "\n",
    "shallow[0].append('Ed')\n",
    "deep[0].append('Fay')\n",
    "\n",
    "print(f\"teams:   {teams}\")\n",
    "print(f\"shallow: {shallow}\")\n",
    "print(f\"deep:    {deep}\")\n",
    "\n",
    "# 'Ed' shows up in teams because shallow[0] and teams[0] are the same inner list.\n",
    "# 'Fay' does not, because deepcopy() copied the inner lists too."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9452b2b",
   "metadata": {},
   "source": [
    "## Summary\n",
    "\n",
    "- `==` compares values; `is` checks whether two names refer to the same object.\n",
    "- Assignment creates an alias, not a copy. When the object is mutable, a change made through one name shows up through the other.\n",
    "- Passing a list to a function passes a reference, so the function can modify the caller's list.\n",
    "- A shallow copy (slicing, `copy()`, `list()`, or `copy.copy()`) creates a new outer list but shares any nested objects.\n",
    "- `copy.deepcopy()` also copies nested objects, so the copy is fully independent."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0f526e5",
   "metadata": {},
   "source": [
    "## Further Reading\n",
    "\n",
    "- [Objects, values and types](https://docs.python.org/3/reference/datamodel.html#objects-values-and-types), Python Language Reference\n",
    "- [Why did changing list 'y' also change list 'x'?](https://docs.python.org/3/faq/programming.html#why-did-changing-list-y-also-change-list-x), Python Programming FAQ\n",
    "- [`copy`: Shallow and deep copy operations](https://docs.python.org/3/library/copy.html), Python Standard Library documentation"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": ".venv",
   "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.13.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
