{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "13e97bad",
   "metadata": {},
   "source": [
    "# Variables and Objects\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "2d5e246a-bb3b-46a0-afb1-fbcc4374ac8c",
   "metadata": {
    "tags": [
     "hide-input",
     "thebe-init"
    ]
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "current = Path.cwd()\n",
    "for parent in [current, *current.parents]:\n",
    "    if (parent / '_config.yml').exists():\n",
    "        project_root = parent  # ← Add project root, not chapters\n",
    "        break\n",
    "else:\n",
    "    project_root = Path.cwd().parent.parent\n",
    "\n",
    "sys.path.insert(0, str(project_root))\n",
    "\n",
    "from shared import thinkpython, diagram, jupyturtle, download\n",
    "\n",
    "# Register as top-level modules so direct imports work in subsequent cells\n",
    "sys.modules['thinkpython'] = thinkpython\n",
    "sys.modules['diagram'] = diagram\n",
    "sys.modules['jupyturtle'] = jupyturtle\n",
    "sys.modules['download'] = download\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "contents",
   "metadata": {},
   "source": [
    "```{contents}\n",
    ":local:\n",
    ":depth: 2\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd117cfa-93f0-4710-8a53-56dd6fdc9b83",
   "metadata": {},
   "source": [
    "```{index} variable\n",
    "```\n",
    "## Variables"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "Programs need a way to remember values. In Python, a **variable** is a named location in computer memory that refers to an **object**. The object stores the **value**; the name lets your program use that value again. Think of a variable as a name/label that is associated with some data. Variables are fundamental to programming because they allow us to store, retrieve, and manipulate data throughout our program. \n",
    "\n",
    "Unlike some other programming languages, Python doesn't require you to **declare** the **data type** of a variable before using it. The type is automatically determined based on the value you assign (this is called **dynamic typing**).\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2fc3da03-6a1b-4c16-98b6-b64a02c1fe7d",
   "metadata": {},
   "source": [
    "### Creating Variables"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-2fc3da03-6a1b-4c16-9",
   "metadata": {},
   "source": [
    "```{index} variable, assignment statement, assignment operator (=)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4ae4d88-64a0-43d7-a98b-0d1dabb9fa96",
   "metadata": {},
   "source": [
    "In Python, you create a variable by using an **assignment statement** with the assignment operator `=`. Read the assignment statement syntax below as \"**assign the value on the right to the name on the left.**\" Python evaluates the right side first, then stores the reference in the name.\n",
    "\n",
    "```python\n",
    "variable_name = value (an expression)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63f921d4-dfc4-4c78-a981-98b3852f0468",
   "metadata": {},
   "source": [
    "An assignment statement has three parts: \n",
    "\n",
    "1. the **name** of the variable on the left,\n",
    "2. the **assignment operator**, **`=`**, and\n",
    "3. an **expression** (the value) on the right."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55ee2966-97f6-4f60-9304-b02563ef5c32",
   "metadata": {},
   "source": [
    "\n",
    "Note that:\n",
    "1. A **variable** is a name that refers to a value.\n",
    "2. When you run an assignment **_statement_**, there is **no output**. Python creates the variable and gives it a value, but the assignment statement has no visible effect.\n",
    "3. A literal value is also an expression.\n",
    "4. After creating a variable, you can use it as an expression. \n",
    "5. Variables can be **reassign**ed.\n",
    "6. You can assign **multiple** values/expressions to multiple variables in one line."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4d568c0-0009-48b3-acac-1579b084b6b9",
   "metadata": {},
   "source": [
    "For example, you can create variables as follows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7ddedf0-ea5d-4ae1-9cad-529430f13bf2",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 1\n",
    "age = 20\n",
    "name = \"Alice\"\n",
    "pi = 3.14\n",
    "is_active = True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40a3fd86-5834-44f9-94e8-424875312a88",
   "metadata": {},
   "source": [
    "\n",
    "You can assign **multiple** values/expressions to multiple variables in one line. For example:\n",
    "- assign multiple variables the same value\n",
    "- assign multiple variables different values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6a97e962-7e9e-4029-b4bb-fa21ffe200d4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x = 0, y = 0, z = 0\n",
      "a = 10, b = 20, c = 30\n"
     ]
    }
   ],
   "source": [
    "x = y = z = 0           # x, y, and z are all 0\n",
    "a, b, c = 10, 20, 30    # assign different values to variables\n",
    "\n",
    "print(f\"x = {x}, y = {y}, z = {z}\")\n",
    "print(f\"a = {a}, b = {b}, c = {c}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03a44889-1c60-4a60-9538-67614e2d0008",
   "metadata": {},
   "source": [
    "Or, you can swap variable values by switching the positions of variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "63e88bf3-3ffe-41f9-9c33-d380a3ee5b2e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Before swap:\t m = 5, n = 10\n",
      "After swap:\t m = 10, n = 5\n"
     ]
    }
   ],
   "source": [
    "m, n = 5, 10            # m is 5 and n is 10\n",
    "print(f\"Before swap:\\t m = {m}, n = {n}\")\n",
    "\n",
    "m, n = n, m             # Swap values using tuple unpacking ==> sorting \n",
    "print(f\"After swap:\\t m = {m}, n = {n}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f04aeba-ce8e-4cf2-aa6b-542b2579f2c3",
   "metadata": {},
   "source": [
    "A name can be rebound to a different object. **Reassignment** does not edit the old object; it makes the name refer to another object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "54b60b53-f1da-4d8d-b3ab-6089f30473c4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "x = 10         # x is 10\n",
    "x = 20.5       # now x is 20.5\n",
    "x = \"hello\"    # now x is a string (type can change!)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b9a67e1e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "draft\n",
      "final\n",
      "label was final and is now final\n",
      "label was final and is now final\n"
     ]
    }
   ],
   "source": [
    "label = \"draft\"\n",
    "print(label)\n",
    "\n",
    "label = \"final\"\n",
    "print(label)\n",
    "\n",
    "print(\"label was\", label, \"and is now\", label)\n",
    "print(f\"label was {label} and is now {label}\")  # f-string"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cf41aea-bb75-4f77-86f6-3330af22be43",
   "metadata": {},
   "source": [
    "```{index} state diagram\n",
    "```\n",
    "#### State diagrams\n",
    "\n",
    "A common way to represent variables on paper is to write the name with an arrow pointing to its value. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "6d7982be-eb94-42ec-a4f8-ae00501d877c",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [],
   "source": [
    "### code for displaying state diagrams\n",
    "### dont' worry about the code here\n",
    "\n",
    "import math\n",
    "\n",
    "from diagram import make_binding, Frame\n",
    "\n",
    "binding = make_binding(\"message\", 'And now for something completely different')\n",
    "binding2 = make_binding(\"n\", 17)\n",
    "binding3 = make_binding(\"pi\", 3.141592653589793)\n",
    "\n",
    "frame = Frame([binding2, binding3, binding])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "5cc09118-5b1a-435a-a591-3c54a3882d59",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 362x101 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "### code for displaying state diagrams\n",
    "### dont' worry about the code here\n",
    "\n",
    "from diagram import diagram, adjust\n",
    "\n",
    "width, height, x, y = [3.62, 1.01, 0.6, 0.76]\n",
    "ax = diagram(width, height)\n",
    "bbox = frame.draw(ax, x, y, dy=-0.25)\n",
    "adjust(x, y, bbox);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38c9b5e9-9dd8-4df3-8ca4-f0497075daf6",
   "metadata": {},
   "source": [
    "This kind of figure is called a **state diagram** because it shows what state each of the variables is in (think of it as the variable's state of mind). This represents a model of how Python stores variables and their values."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9984987f-1be4-4950-b987-8fbb615215af",
   "metadata": {},
   "source": [
    "```{index} variable: naming convention\n",
    "```\n",
    "### Naming Conventions\n",
    "\n",
    "General Python variable naming follows the convention from the official [PEP 8 style guidelines](https://peps.python.org/pep-0008/#naming-conventions), although conventions such as Google Python:\n",
    "\n",
    "1. Length: Names can be as long as you like.\n",
    "2. Containing: Names can contain alphanumeric characters (letters and numbers) and underscores. Special characters (e.g., @, #, $) are not allowed.\n",
    "3. Begin with: Can begin with an **underscore** or a **letter**, but can't begin with a number.\n",
    "4. Letter Case:\n",
    "   1. Names are case-sensitive. `age`, `Age`, and `AGE` are three distinct variables.\n",
    "   2. It is conventional to use only **lowercase** letters for variable names, although it is legal to use uppercase letters.\n",
    "   3. Use **`snake_case`** for variable names: All lowercase with **underscores** between words. Example: total_price, student_name, is_active. (camelCase is for C#/Java/JavaScript variable names.)\n",
    "   4. For class names, use **PascalCase**, or `upper camel case`, convention; e.g., `class StudentRecord`. \n",
    "7. Avoid **keywords** and **built-in function** names for naming variables.\n",
    "8. Constants: For constants, use ALL_CAPS with underscores; e.g., MAX_SIZE = 100, PI = 3.14159.\n",
    "\n",
    "The only punctuation that can appear in a variable name is the underscore character, `_`. It is often used in names with multiple words, such as `your_name` or  `airspeed_of_unladen_swallow`.\n",
    "\n",
    "If you give a variable an illegal name, you get a syntax error. For example, the name `million!` is illegal because it contains punctuation.\n",
    "\n",
    "Python programmers follow these **conventions** (recommended but not required):\n",
    "\n",
    "| Convention | Use Case | Example |\n",
    "|------------|----------|---------|\n",
    "| **snake_case** | Variable and function names | `student_name`, `total_price` |\n",
    "| UPPER_CASE | Constants | `MAX_SIZE`, `PI` |\n",
    "| PascalCase (not camelCase) | Class names | `StudentRecord`, `BankAccount` |\n",
    "| **Descriptive** names | Make code readable | `count` instead of `c` |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7ba23cc-91a9-4fc1-ba30-e1e626c6284e",
   "metadata": {},
   "source": [
    "To show all the Python keywords (which you don't want to use as variable names):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "f9e941a5-da0d-4185-b142-1e544e447ab5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of Python keywords: 35\n",
      "First five Python keywords: ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']\n"
     ]
    }
   ],
   "source": [
    "from keyword import kwlist\n",
    "\n",
    "print(\"Number of Python keywords:\", len(kwlist))\n",
    "print(\"First five Python keywords:\", kwlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "995f194a-10a0-400b-8413-4cf7a7808d50",
   "metadata": {},
   "source": [
    "Good naming makes code easier to scan and therefore is great for **documentation**. In Python, variable names usually use **`snake_case`**: lowercase words separated by underscores.\n",
    "\n",
    "| Pattern | Use |\n",
    "|---|---|\n",
    "| `student_count` | regular variable |\n",
    "| `MAX_RETRIES` | constant by convention |\n",
    "| `_temporary` | internal helper name by convention |\n",
    "\n",
    "Avoid names that shadow common built-ins, such as `list`, `sum`, `str`, or `type`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "f99f705e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "28 84.6 True\n"
     ]
    }
   ],
   "source": [
    "student_count = 28\n",
    "average_score = 84.6\n",
    "is_passing = average_score >= 70\n",
    "print(student_count, average_score, is_passing)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "97f5f6aa",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Create useful names\n",
    "# Create variables named course_name, enrolled_students, and average_grade.\n",
    "# Print a sentence like: Python has 28 students with an average grade of 84.6.\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "97f5f6aa-answer",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python has 28 students with an average grade of 84.6.\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "course_name = \"Python\"\n",
    "enrolled_students = 28\n",
    "average_grade = 84.6\n",
    "\n",
    "print(f\"{course_name} has {enrolled_students} students with an average grade of {average_grade}.\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a0eecf1-d49f-4a8f-97fd-be41eb321f72",
   "metadata": {},
   "source": [
    "### Expressions and Arguments"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-9a0eecf1-d49f-4a8f-9",
   "metadata": {},
   "source": [
    "```{index} expression, argument\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36de7be4-f57d-4e21-bd5f-7c53459ee06c",
   "metadata": {},
   "source": [
    "After you create a variable, you can use it as an **expression**. In this example below, the expression is an integer (a literal is an expression in Python). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8899c3e5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "92\n"
     ]
    }
   ],
   "source": [
    "score = 87\n",
    "bonus = 5\n",
    "score = score + bonus     ### expression with + operator\n",
    "print(score)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7a8b050-32ad-4aa8-9a4a-30457112de20",
   "metadata": {},
   "source": [
    "In the following examples, the expressions are:\n",
    "- a floating-point number\n",
    "- an expression (`pi * 2`)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "596c739e-d9f4-4047-9322-496296d60ca2",
   "metadata": {},
   "outputs": [],
   "source": [
    "pi = 3.141592653589793\n",
    "pi2 = pi * 2\n",
    "message = \"This week\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0d6a01c-41b9-4d00-b6d3-1e73e486b347",
   "metadata": {},
   "source": [
    "You can also use a **variable** as part of an expression with arithmetic operators."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "175f881f-2bdb-4468-a65e-9d0291c268fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "42\n",
      "6.283185307179586\n",
      "And now for something completely different we will learn Python\n"
     ]
    }
   ],
   "source": [
    "print(n + 25)\n",
    "print(2 * pi)\n",
    "print(message + \" we will learn Python\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57fb2b17-b9d4-40bb-b23e-e557df27685f",
   "metadata": {},
   "source": [
    "And you can use variables as the **arguments** when you call a function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "04b5891f-0c17-4bf1-8de2-081c8a015233",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "42\n"
     ]
    }
   ],
   "source": [
    "print(round(pi))       ### \"round()\" is a built-in function\n",
    "print(len(message))    ### the number of characters in the string "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "55c85083",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "course = \"Python\"\n",
    "week = 2\n",
    "print(course)\n",
    "print(week)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-vars-expr-ex",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Compute with variables\n",
    "# A fruit stand sells apples for 0.65 dollars each.\n",
    "# 1. Create the variables apple_price (0.65) and apple_count (12).\n",
    "# 2. Use them in an expression to create the variable total_cost.\n",
    "# 3. Pass total_cost as an argument to round() to round it to 1 decimal place.\n",
    "# 4. Print a sentence like: 12 apples cost 7.8 dollars.\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-vars-expr-ex-answer",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "7.800000000000001\n12 apples cost 7.8 dollars.\n"
    }
   ],
   "source": [
    "### Solution\n",
    "apple_price = 0.65\n",
    "apple_count = 12\n",
    "\n",
    "total_cost = apple_price * apple_count\n",
    "print(total_cost)\n",
    "\n",
    "rounded_cost = round(total_cost, 1)\n",
    "print(f\"{apple_count} apples cost {rounded_cost} dollars.\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "255ba181",
   "metadata": {},
   "source": [
    "## Python Objects\n",
    "\n",
    "In Python, [everything is an **object**](https://www.pythonmorsels.com/everything-is-an-object/), including classes, instances of classes, modules, and functions. In short, anything that you can point a **variable** to is an **object**. Variables in Python do not **save** values as *buckets* containing things; they're pointers pointing to objects.\n",
    "\n",
    "\n",
    "\n",
    "In Python, \"everything is an **object**\", and every object has a value, a type, and an identity: \n",
    "\n",
    "- **identity** (unique ID) (`id()`): Each object has a unique identifier that remains constant for the object's lifetime. You can retrieve it with the built-in `id()` function. In CPython, the standard Python interpreter, this number is the object's memory address; other Python implementations may use a different number.\n",
    "- **value**: This represents the data that the object stores. \n",
    "- **type** (data type): An object's type defines what kind of data it represents and what operations can be performed on it. The type of an object can be determined using the built-in type() function, and every object is an instance of some class. \n",
    "\n",
    "\n",
    "You can use `type()` to inspect the kind of data the object refers to, and use `id()` to find the identification the object has."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-255ba181",
   "metadata": {},
   "source": [
    "```{index} object, reference\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c97f48f-fe37-4e10-b7ea-84bfeefea690",
   "metadata": {},
   "source": [
    "### Data Type\n",
    "\n",
    "The values that are associated with the object can be checked by using the`type()` function."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-6c97f48f-fe37-4e10-b",
   "metadata": {},
   "source": [
    "```{index} data type, type()\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "0a9ffc97",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'int'>\n",
      "<class 'float'>\n",
      "<class 'str'>\n",
      "<class 'bool'>\n"
     ]
    }
   ],
   "source": [
    "### check data type\n",
    "\n",
    "items = 12\n",
    "price = 4.99\n",
    "name = \"notebook\"\n",
    "in_stock = True\n",
    "\n",
    "print(type(items))\n",
    "print(type(price))\n",
    "print(type(name))\n",
    "print(type(in_stock))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe7e7aa9",
   "metadata": {},
   "source": [
    "### Object ID\n",
    "In Python, every object has a unique identity, which can be obtained using the built-in `id()` function. An identity is a unique integer that remains constant for an object throughout its lifetime. This is useful for understanding how Python manages objects in memory and for distinguishing between objects that have the same value. \n",
    "\n",
    "You can use the `id()` function when you need to reason about identity. In the examples below, each variable is bound to a different object, so each `id()` is different."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-fe7e7aa9",
   "metadata": {},
   "source": [
    "```{index} object ID, id()\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "19b71d07-edc0-435a-bc49-c280f61e66f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4340770080\n",
      "4453727120\n",
      "4456924192\n",
      "4462068416\n"
     ]
    }
   ],
   "source": [
    "### different objects have different IDs\n",
    "\n",
    "num1 = 42\n",
    "num2 = 3.14\n",
    "greeting = \"hello\"\n",
    "fruits = [\"apple\", \"banana\", \"cherry\"]\n",
    "\n",
    "print(id(num1))\n",
    "print(id(num2))\n",
    "print(id(greeting))\n",
    "print(id(fruits))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "08d2c255-c9ad-4ec2-a59c-8db6439369b9",
   "metadata": {},
   "source": [
    "### Mutability\n",
    "\n",
    "Some objects can be changed after the variables are created, and some can not:\n",
    "- **Mutable**: Data collection types such as `list`, `dict` (dictionary), and `set` are mutable. After creating variables with such data, you may change (update) the data. \n",
    "- **Immutable**: Data types such as integers, floats, strings, booleans, `None`, and tuples are immutable. You can not change (update) the value after the variables are created. In order to change the object value to the variable name, you have to perform a new assignment (reassignment). "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-08d2c255-c9ad-4ec2-a",
   "metadata": {},
   "source": [
    "```{index} mutability, mutation, reassignment\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e42a378-c0de-45d6-82ad-7ffb0fd93c3e",
   "metadata": {},
   "source": [
    "| Action | What actually happens | Identity (`id()`) |\n",
    "|---|---|---|\n",
    "| **Reassignment** (`x = new_value`) | `x` is repointed to a *different* object entirely | Changes |\n",
    "| **Mutation** (`x.append(...)`, `x[0] = ...`) | The *same* object's contents change in place | Stays the same |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "5947c9ce-e924-4ce0-bddb-5f50b586ec00",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3] 4462080320\n",
      "[1, 2, 3, 4] 4462080320\n"
     ]
    }
   ],
   "source": [
    "### mutation: different value, same ID\n",
    "\n",
    "x = [1, 2, 3]\n",
    "\n",
    "print(x, id(x))\n",
    "\n",
    "x.append(4)     ### mutation; data (object) updated\n",
    "\n",
    "print(x, id(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "3651cedb-0a52-4d7e-8218-2375d83e95c0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 4340768896\n",
      "6 4340768928\n"
     ]
    }
   ],
   "source": [
    "### reassignment: different value, different ID\n",
    "\n",
    "num = 5\n",
    "print(num, id(num))\n",
    "\n",
    "num = 5 + 1      ### reassignment; new object created\n",
    "print(num, id(num))\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "96ec45d2-7601-40d8-93fb-ed466d6ade4b",
   "metadata": {},
   "source": [
    "**A note on identity**\n",
    "\n",
    "Assignment does not create an object or an ID; it **binds** a name to an object. In `num = 5 + 1`, the expression `5 + 1` produces the object and the assignment binds `num` to it. Assigning one name to another, as in `b = a`, creates no new object at all: both names refer to the same object and share one ID. Two names for the same object are called **aliases**.\n",
    "\n",
    "When two names are bound to separately created objects, the IDs usually differ even if the values are equal. For **immutable** types, however, Python may reuse an existing object instead of creating a new one to save memory, so equal values **may** share an ID. \n",
    "\n",
    "In the example below, small integer literals are *interned* — reused as the same object — as a memory optimization. This is a CPython implementation detail, not something your code should ever rely on. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-alias-same-id",
   "metadata": {},
   "outputs": [],
   "source": [
    "### aliasing: two names, one object\n",
    "\n",
    "a = [1, 2, 3]\n",
    "b = a           ### no new object; b is bound to the same list\n",
    "print(id(a))\n",
    "print(id(b))\n",
    "print(a is b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "d3281169-0d1c-4062-aad0-d52cb132decc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4340771936\n",
      "4340771936\n"
     ]
    }
   ],
   "source": [
    "### small int, same IDs\n",
    "\n",
    "num1=100\n",
    "num2=100\n",
    "print(id(num1))\n",
    "print(id(num2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "17781d90-fe3b-426e-b688-639e1854b92b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4461131632\n",
      "4461124240\n"
     ]
    }
   ],
   "source": [
    "### large int, different IDs\n",
    "\n",
    "num1=1000\n",
    "num2=1000\n",
    "print(id(num1))\n",
    "print(id(num2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "55452105-8e4f-4e0b-a6fa-a80af56d24af",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4340622136\n",
      "4340622136\n"
     ]
    }
   ],
   "source": [
    "### None, same ID\n",
    "\n",
    "a = None\n",
    "b = None\n",
    "print(id(a))\n",
    "print(id(b))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c3678c6-6b57-4825-a137-958d601e0f4c",
   "metadata": {},
   "source": [
    "### Aliasing\n",
    "Aliasing happens when two or more variable names refer to the **same object** in memory, rather than each having its own independent copy. Because they point to the same object, changing the object through one name is visible through the other name too. \n",
    "\n",
    "When two names refer to the same **mutable object**, changing the object through one name affects what you see through the other name. This is called **aliasing**, meaning different variables with the same value will have not only the same values but also the same IDs.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "idx-2c3678c6-6b57-4825-a",
   "metadata": {},
   "source": [
    "```{index} aliasing\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe965f6f-3fce-4b1a-ad8f-abac159463fa",
   "metadata": {},
   "source": [
    "Let's start with creating two `list` variables by using two assignment statements and observe their values and IDs. You can see that they have the same values but with different IDs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "90028699-f874-4819-affd-7894adfb75a4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 20, 30]\n",
      "[10, 20, 30]\n",
      "4462081728\n",
      "4461919872\n"
     ]
    }
   ],
   "source": [
    "a = [10, 20, 30]\n",
    "b = [10, 20, 30]\n",
    "\n",
    "print(a)\n",
    "print(b)\n",
    "\n",
    "print(id(a))\n",
    "print(id(b))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ff1ee99-8e73-4948-82de-6a31e4356733",
   "metadata": {},
   "source": [
    "Now we'll check their value equality and identity by using the keyword `is` and the operator `==`. You see that they have the same value, but they are different objects; which means the value binds to list `b` is a different copy from list `a`. They just happen to be the same value. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "5070632b-b5c0-430d-a264-95d1c0e56cf6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(a == b)             ### True; same value\n",
    "print(a is b)             ### False; different ID == different objects"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "708fd1be-fde0-4d84-97ad-eeb818234c26",
   "metadata": {},
   "source": [
    "Since variables are just names, two variables can point to the same object — and if that object is mutable, changing it through one name is visible through the other.\n",
    "\n",
    "In the example below, you can see that both list `a` and `b` have the same value and the same ID. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d50e7749-90b7-4b7c-bd52-42f8498a7b9b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 20, 30]\n",
      "[10, 20, 30]\n",
      "4437292864\n",
      "4437292864\n"
     ]
    }
   ],
   "source": [
    "### a and b have the same value and the same ID\n",
    "a = [10, 20, 30]\n",
    "b = a     ### b is now an ALIAS for a — same object, not a copy\n",
    "\n",
    "print(a)\n",
    "print(b)\n",
    "\n",
    "print(id(a))\n",
    "print(id(b))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a32545f6-7822-4be1-ba1f-4f85f45261c1",
   "metadata": {},
   "source": [
    "Since they have the same ID, both variable names point to the same object. The data variable `a` points to is the same copy `b` points to -- there's only one copy (same object)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76a337ea-7204-46e8-a372-d7b0a34bf832",
   "metadata": {},
   "source": [
    "#### Sameness\n",
    "\n",
    "Here, you use the `==` operator to check value equality and the `is` keyword to check object identity. \n",
    "\n",
    "- **Equality** Operators: **`==`** and **`!=`**. These check if two values are equal (have the same content).\n",
    "- **Identity** Operator: **`is`**. This checks if two variables point to the same object in memory (aliasing!)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "725c96d3-438c-4b71-b029-0372fe97944c",
   "metadata": {},
   "source": [
    "As a summary of the equity and identiity operators:\n",
    "\n",
    "| Operator | Purpose | Example | What it checks |\n",
    "|----------|---------|---------|----------------|\n",
    "| `==` | Equality | `[1,2] == [1,2]` | Do they have the same content? |\n",
    "| `!=` | Inequality | `[1,2] != [3,4]` | Do they have different content? |\n",
    "| `is` | Identity | `x is y` | Do they point to the same object? |\n",
    "| `is not` | Non-identity | `x is not y` | Do they point to different objects? |\n",
    "\n",
    "Or, simply:\n",
    "\n",
    "| Operator | Checks   | Meaning     |\n",
    "| -------- | -------- | ----------- |\n",
    "| `is`     | Identity | Same object |\n",
    "| `==`     | Equality | Same value  |\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7aa68928",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(a == b)             ### True; same value\n",
    "print(a is b)             ### True; same ID == same object"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62c59cfd-83af-4a79-a0aa-cd0b36335055",
   "metadata": {},
   "source": [
    "The surprising side effect is that if you update the value of one variable, the other variable will reflect the change as well, since they are the same object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "622adb7a-b476-458f-ac28-9e4b5fc1abaa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 20, 30]\n",
      "[10, 20, 30]\n",
      "\n",
      "a == b:  True\n",
      "a is b:  True\n",
      "id(a) == id(b)  True\n",
      "[10, 20, 30] 4437423872\n",
      "[10, 20, 30] 4437423872\n",
      "\n",
      "b.append(40)\n",
      "\n",
      "[10, 20, 30, 40] 4437423872\n",
      "[10, 20, 30, 40] 4437423872\n"
     ]
    }
   ],
   "source": [
    "a = [10, 20, 30]\n",
    "b = a                     ### b is an \"alias\" of a\n",
    "\n",
    "print(a)                  ### [10, 20, 30]\n",
    "print(b)                  ### [10, 20, 30]\n",
    "\n",
    "print()\n",
    "\n",
    "print(\"a == b: \", a == b)     ### '==' for equality (same value) test\n",
    "print(\"a is b: \", a is b)     ### '==' for equality (same value) test\n",
    "print(\"id(a) == id(b) \", id(a) == id(b))\n",
    "print(a, id(a))         ### a is changed as well because a and b are the same object\n",
    "print(b, id(b))\n",
    "\n",
    "print()\n",
    "\n",
    "print(\"b.append(40)\")\n",
    "b.append(40)     ### change b\n",
    "\n",
    "print()\n",
    "\n",
    "print(a, id(a))         ### a is changed as well because a and b are the same object\n",
    "print(b, id(b))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d92b3896-ed75-4b1b-85c1-df6636393c6e",
   "metadata": {},
   "source": [
    "Another example of aliasing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "01d0348a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nums is [1, 2, 3] and has id 4431464320\n",
      "alias is [1, 2, 3] and has id 4431464320\n",
      "\n",
      "modifying the list using the alias...\n",
      "\n",
      "alias is now [1, 2, 3, 4] and has id 4431464320\n",
      "nums is now [1, 2, 3, 4] too, and has id 4431464320\n"
     ]
    }
   ],
   "source": [
    "nums = [1, 2, 3]\n",
    "print(f\"nums is {nums} and has id {id(nums)}\")\n",
    "\n",
    "alias = nums    ### Create an alias for nums\n",
    "print(f\"alias is {alias} and has id {id(alias)}\")\n",
    "\n",
    "print(\"\\nmodifying the list using the alias...\")\n",
    "alias.append(4) ### Modify the list using the alias\n",
    "print(f\"\\nalias is now {alias} and has id {id(alias)}\")\n",
    "\n",
    "print(f\"nums is now {nums} too, and has id {id(nums)}\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ef6a9e8a-2ce1-4020-b3a9-4721e6115dc6",
   "metadata": {},
   "source": [
    "This side effect does not happen with literal data types such as strings, which are **immutable**. \n",
    "\n",
    "For `list` and `dict` collection types, to avoid the side effect of **mutable** aliasing, you may:\n",
    "\n",
    "- Use **reassignment** with the alias variable. Reassignment moves one name to a new object; it does not change the original object.\n",
    "- Use the .copy() method to create an independent copy of the original object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1b1e0102",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3]\n",
      "[1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "nums = [1, 2, 3]\n",
    "alias = nums\n",
    "\n",
    "alias = [1, 2, 3, 4]    #### reassignment to alias\n",
    "print(nums)\n",
    "print(alias)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "049e8be8",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['orange', 'green', 'blue', 'purple']\n"
     ]
    }
   ],
   "source": [
    "### Exercise: Mutation or reassignment?\n",
    "# For each line below, add a comment saying whether it mutates an object or reassigns a name.\n",
    "colors = [\"red\", \"green\"]\n",
    "colors.append(\"blue\")\n",
    "colors = colors + [\"purple\"]\n",
    "colors[0] = \"orange\"\n",
    "print(colors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "049e8be8-answer",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['orange', 'green', 'blue', 'purple']\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "colors = [\"red\", \"green\"]\n",
    "colors.append(\"blue\")          # mutates the existing list\n",
    "colors = colors + [\"purple\"]   # reassigns colors to a new list\n",
    "colors[0] = \"orange\"           # mutates the list\n",
    "print(colors)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-sameness-ex",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Equal or the same object?\n",
    "# 1. Create the list fruits = [\"apple\", \"banana\"].\n",
    "# 2. Create copy_fruits as a separate list literal with the same items.\n",
    "# 3. Create alias_fruits as an alias of fruits.\n",
    "# 4. Print fruits == copy_fruits, fruits is copy_fruits, and fruits is alias_fruits.\n",
    "# 5. Append \"cherry\" through alias_fruits, then print fruits and copy_fruits.\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-sameness-ex-answer",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "True\nFalse\nTrue\n['apple', 'banana', 'cherry']\n['apple', 'banana']\n"
    }
   ],
   "source": [
    "### Solution\n",
    "fruits = [\"apple\", \"banana\"]\n",
    "copy_fruits = [\"apple\", \"banana\"]    # equal value, different object\n",
    "alias_fruits = fruits                # same object\n",
    "\n",
    "print(fruits == copy_fruits)         # True\n",
    "print(fruits is copy_fruits)         # False\n",
    "print(fruits is alias_fruits)        # True\n",
    "\n",
    "alias_fruits.append(\"cherry\")        # mutates the object fruits refers to\n",
    "print(fruits)\n",
    "print(copy_fruits)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c878b081",
   "metadata": {},
   "source": [
    "## Summary\n",
    "\n",
    "- Assignment binds a name to an object.\n",
    "- Objects have values, types, and identities.\n",
    "- `==` checks equal value; `is` checks same object.\n",
    "- Mutation changes an object; reassignment changes which object a name refers to.\n",
    "- F-strings are the standard way to combine text and values for output."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "29d6ea13-916d-4cd0-ad3c-b5922fa7bc44",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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
}
