{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d0286422",
   "metadata": {},
   "source": [
    "# Variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9e983a2b",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": [
     "hide-input"
    ]
   },
   "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, structshape\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",
    "sys.modules['structshape'] = structshape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32f9b403",
   "metadata": {},
   "source": [
    "A **variable** is a named location in computer memory that stores a value. Think of it 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**)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe624804",
   "metadata": {},
   "source": [
    "## Naming Rules & 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. Names must start with a letter (a-z, A-Z) or underscore (`_`)\n",
    "4. **Case-sensitive**: `Name`, `name`, and `NAME` are different variables\n",
    "5. Avoid **keywords** and **built-in function** names (like `if`, `for`, `class`, etc.) for naming variables.\n",
    "6. Constants: For constants, use ALL_CAPS with underscores; e.g., MAX_SIZE = 100, PI = 3.14159.\n",
    "7. 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",
    "\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": "d24736db",
   "metadata": {},
   "source": [
    "## Creating Variables"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fa73ba5",
   "metadata": {},
   "source": [
    "In Python, you create a variable by using an **assignment statement** with the assignment operator `=`. The syntax for creating variables is:\n",
    "\n",
    "```python\n",
    "variable_name = value\n",
    "```\n",
    "\n",
    "An assignment statement has three parts: \n",
    "\n",
    "1. the **name** of the variable on the left,\n",
    "2. the equals operator, **`=`**, and\n",
    "3. an **expression** on the right."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "beadb716",
   "metadata": {},
   "source": [
    "For example, we can create variables as follows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "76d8a7d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 1\n",
    "age = 20\n",
    "name = \"Alice\"\n",
    "pi = 3.14\n",
    "is_active = True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f22bcba9",
   "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": "8f7303a2",
   "metadata": {},
   "source": [
    "You can **reassign** a variable and the last value assigned is the one that stays."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8afcf244",
   "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": "markdown",
   "id": "e995e6c8",
   "metadata": {},
   "source": [
    "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": 5,
   "id": "a555128a",
   "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": "8f0cc57e",
   "metadata": {},
   "source": [
    "Or, you can swap variable values by switch the positions of variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "0b274bcb",
   "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": "2aed1f12",
   "metadata": {},
   "source": [
    "In the following examples, the values/expressions have different **data types**:\n",
    "- a floating-point number\n",
    "- an expression (`pi * 2`)\n",
    "- a string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "90634171",
   "metadata": {},
   "outputs": [],
   "source": [
    "pi = 3.141592653589793\n",
    "pi2 = pi * 2\n",
    "message = 'And now for something completely different'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3ef8615",
   "metadata": {},
   "source": [
    "A common way to represent variables is to write the name with an arrow pointing to its value. 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).\n",
    "We'll use state diagrams throughout the book to represent a model of how Python stores variables and their values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "635b5a97",
   "metadata": {},
   "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": 9,
   "id": "655e87cc",
   "metadata": {},
   "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": "055910ed",
   "metadata": {},
   "source": [
    "You can also use a **variable** as part of an expression with operators."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "13f2194b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.141592653589793\n",
      "6.283185307179586\n"
     ]
    }
   ],
   "source": [
    "print(pi + 1)\n",
    "print(2 * pi)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06fa032d",
   "metadata": {},
   "source": [
    "And you can use a variable when you call a function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f9b79868",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "42"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "round(pi)       ### \"round()\" is a built-in function\n",
    "len(message)    ### the number of characters in the string "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "49609bf0",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Create a variable called \"name\" and use f-string to print it\n",
    "### The output should be the same as the cell below\n",
    "### Your code starts here\n",
    "\n",
    "\n",
    "### Your code ends here"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "d26af38a",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Dr. Chen\n"
     ]
    }
   ],
   "source": [
    "name = \"Dr. Chen\"\n",
    "print(f\"Hello, {name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "074c32ff",
   "metadata": {},
   "source": [
    "```{index} keywords\n",
    "```\n",
    "## Python Keywords \n",
    "\n",
    "Python reserved words, or keywords, are words that you are not supposed to use for variable names.\n",
    "\n",
    "Keywords are special words reserved by the programming language to be used to specify the **structure** of a program. Keywords of the language cannot be used as ordinary identifiers. For example, if you try to assign a string to a variable name _class_, since `class` is a **keyword**, you will receive a syntax error because the Python interpreter will detect that. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "c3ef94a0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Positive number\n"
     ]
    }
   ],
   "source": [
    "num = 5\n",
    "if num > 0:\n",
    "    print(\"Positive number\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f2f414d",
   "metadata": {},
   "source": [
    "### Soft keywords\n",
    "\n",
    "Python's soft keywords are special words that act as keywords only within specific contexts, but can be used as regular identifiers (like variable or function names) in other contexts. As of Python 3.12, there are 4 [soft keywords](https://docs.python.org/3.13/reference/lexical_analysis.html#soft-keywords): **match**, **case**, **_**, and **type**."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4186bb60",
   "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."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fe08672",
   "metadata": {},
   "source": [
    "In Python, everything is an **object**, and every object has: \n",
    "\n",
    "- **identity** (unique ID) (`id()`): Each object has a unique identifier that remains constant for the object's lifetime. This is the object's memory address and can be retrieved using the built-in id() function.\n",
    "- **value**: This represents the data that the object stores. For some object types (such as integers, strings, or tuples), the value is immutable (cannot be changed after creation), whereas for others (such as lists or dictionaries), it is mutable (can be changed).\n",
    "- **type** (`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. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00b5ea59",
   "metadata": {},
   "source": [
    "### Object ID\n",
    "\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. \n",
    "\n",
    "This is useful for understanding how Python manages objects in memory and for distinguishing between objects that have the same value. Note these objects have different id's."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f5107bb",
   "metadata": {},
   "source": [
    "#### `id()`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a79be50b",
   "metadata": {},
   "source": [
    "We use the `id()` function to check the object's id. As you see, id's are unique here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "11f09a6a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4322681120\n",
      "4568309392\n",
      "4569686256\n",
      "4568046592\n"
     ]
    }
   ],
   "source": [
    "num1 = 10                   ### integer\n",
    "num2 = 10.1                 ### floating-point number\n",
    "greeting = \"hello, world\"   ### text/string\n",
    "fruits = ['Apple', 'Banana', 'Cherry']      ### lists are enclosed with square brackets\n",
    "\n",
    "print(id(num1))\n",
    "print(id(num2))\n",
    "print(id(greeting))\n",
    "print(id(fruits))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5623118f",
   "metadata": {},
   "source": [
    "The example below is peculiar. If two variables point to the same **literal** values, then they have the same id, even though they are created separately. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "28bdbf6d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4322684000\n",
      "4322684000\n",
      "4437166672\n",
      "4437166672\n"
     ]
    }
   ],
   "source": [
    "num1 = 100\n",
    "num2 = 100\n",
    "string1 = \"hello\"\n",
    "string2 = \"hello\"\n",
    "\n",
    "print(id(num1))\n",
    "print(id(num2))\n",
    "print(id(string1))\n",
    "print(id(string2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8433c03d",
   "metadata": {},
   "source": [
    "However, if the **collections** are assigned separately, they do not share the same `id`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "dbea7402",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4567168960\n",
      "4568047296\n"
     ]
    }
   ],
   "source": [
    "nums1 = [1, 2, 3, 4, 5 ]\n",
    "nums2 = [1, 2, 3, 4, 5 ]\n",
    "\n",
    "print(id(nums1))\n",
    "print(id(nums2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17d2d9ce",
   "metadata": {},
   "source": [
    "#### Aliasing"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31d16f5a",
   "metadata": {},
   "source": [
    "In the example below, `num1` and `num2` point to the same object, and they therefore have the same `id`. `num2` is an **alias** of `num1`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "0403e831",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num1 id: 4322681120\n",
      "num2 id: 4322681120\n"
     ]
    }
   ],
   "source": [
    "num1 = 10            ### integer\n",
    "num2 = num1          ### num2 now references the same object as num1    \n",
    "\n",
    "print(f\"num1 id: {id(num1)}\")\n",
    "print(f\"num2 id: {id(num2)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d087995",
   "metadata": {},
   "source": [
    "Instead of literals, let us observe the collection type objects. We see that, just like strings, `nums1` and its alias share the same **id** and the same **value**. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "f4dabe6c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "nums1:\t\t id: 4567904640 values: [1, 2, 3, 4, 5]\n",
      "nums2:\t\t id: 4567904640 values: [1, 2, 3, 4, 5]\n"
     ]
    }
   ],
   "source": [
    "nums1 = [1, 2, 3, 4, 5 ]    ### lists are enclosed with square brackets\n",
    "nums2 = nums1\n",
    "\n",
    "print(f\"nums1:\\t\\t id: {id(nums1)} values: {nums1}\")\n",
    "print(f\"nums2:\\t\\t id: {id(nums2)} values: {nums2}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ab5368a",
   "metadata": {},
   "source": [
    "To understand these behavior between the variable names and the objects in memory, we can look at the them as two separate zones."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cb4c04b",
   "metadata": {},
   "source": [
    "At first, two variables (`nums1`, `nums2`) are created, one with assignment and the other with aliasing, and now their share the same object references."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac12d879",
   "metadata": {},
   "source": [
    "```{mermaid}\n",
    "%%{init: {'theme':'base', 'themeVariables': { 'fontSize':'10px'}}}%%\n",
    "flowchart LR\n",
    "\n",
    "  %% -----------------------\n",
    "  %% Variable Land\n",
    "  %% -----------------------\n",
    "  subgraph VL[\"Variable Land\"]\n",
    "    nums1[\"nums1\"]\n",
    "    nums2[\"nums2\"]\n",
    "  end\n",
    "\n",
    "  %% -----------------------\n",
    "  %% Object Land\n",
    "  %% -----------------------\n",
    "  subgraph OL[\"Object Land\"]\n",
    "    list1[\"list[1, 2, 3, 4, 5]\"]\n",
    "  end\n",
    "\n",
    "  %% -----------------------\n",
    "  %% References\n",
    "  %% -----------------------\n",
    "  nums1 --> list1\n",
    "  nums2 --> list1\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18e588df",
   "metadata": {},
   "source": [
    "When we update the values of the nums2, we see that nums1 is changed as well. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "5f567421",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4569766016 [1, 2, 3, 4, 5000]\n",
      "4569766016 [1, 2, 3, 4, 5000]\n"
     ]
    }
   ],
   "source": [
    "nums2[4] = 5000\n",
    "\n",
    "print(id(nums1), nums1)\n",
    "print(id(nums2), nums2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3e0a117",
   "metadata": {},
   "source": [
    "That is because both `nums1` and `nums2` are still pointing to the same object."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a2858e4",
   "metadata": {},
   "source": [
    "```{mermaid}\n",
    "%%{init: {'theme':'base', 'themeVariables': { 'fontSize':'10px'}}}%%\n",
    "flowchart LR\n",
    "\n",
    "  %% -----------------------\n",
    "  %% Variable Land\n",
    "  %% -----------------------\n",
    "  subgraph VL[\"Variable Land\"]\n",
    "    nums1[\"nums1\"]\n",
    "    nums2[\"nums2\"]\n",
    "  end\n",
    "\n",
    "  %% -----------------------\n",
    "  %% Object Land\n",
    "  %% -----------------------\n",
    "  subgraph OL[\"Object Land\"]\n",
    "    list1[\"list[1, 2, 3, 4, 5000]\"]\n",
    "  end\n",
    "\n",
    "  %% -----------------------\n",
    "  %% References\n",
    "  %% -----------------------\n",
    "  nums1 --> list1\n",
    "  nums2 --> list1\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77422993",
   "metadata": {},
   "source": [
    "However, if we reassign (**assignment**) the `nums2` instead of updating (**aliasing**), we see that nums2 now points to a different object (**id**), even though we assign the same values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "bb35102d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4567904640 [1, 2, 3, 4, 5]\n",
      "4567352192 [1, 2, 3, 4, 5000]\n"
     ]
    }
   ],
   "source": [
    "nums2 = [1, 2, 3, 4, 5000]\n",
    "\n",
    "print(id(nums1), nums1)\n",
    "print(id(nums2), nums2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fd0d5a7",
   "metadata": {},
   "source": [
    "Because assignments with container types create new object even though they have the same values. This is unlike the case with creating literal value variables."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "737bd07f",
   "metadata": {},
   "source": [
    "```{mermaid}\n",
    "%%{init: {'theme':'base', 'themeVariables': { 'fontSize':'10px'}}}%%\n",
    "flowchart LR\n",
    "  subgraph VL[\"Variable Land\"]\n",
    "    nums1[\"nums1\"]\n",
    "    nums2[\"nums2\"]\n",
    "  end\n",
    "  \n",
    "  subgraph OL[\"Object Land\"]\n",
    "    list1[\"list[1, 2, 3, 4, 5000]\"]\n",
    "    list2[\"list[1, 2, 3, 4, 5000]\"]\n",
    "  end\n",
    "  \n",
    "  nums1 --> list1\n",
    "  nums2 --> list2\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b97b2321",
   "metadata": {},
   "source": [
    "## Sameness"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "02df48d2",
   "metadata": {},
   "source": [
    "- **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": "code",
   "execution_count": null,
   "id": "1e4c6d75",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# Value equality\n",
    "\n",
    "x = [1, 2, 3]\n",
    "y = [1, 2, 3]\n",
    "print(x == y)              # True (same content)\n",
    "print(x != y)              # False\n",
    "\n",
    "# String equality\n",
    "name1 = \"Chen\"\n",
    "name2 = \"Chen\"\n",
    "print(name1 == name2)      # True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3b7bc23",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "### is: identity\n",
    "x = [1, 2, 3]\n",
    "y = [1, 2, 3]\n",
    "print(x == y)              # True (equal values)\n",
    "print(x is y)              # False (different objects)\n",
    "\n",
    "# Aliasing - same object\n",
    "x = [1, 2, 3]\n",
    "y = x                      # Alias!\n",
    "print(x == y)              # True (equal values)\n",
    "print(x is y)              # True (same object)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "641b22a8",
   "metadata": {},
   "source": [
    "As a summary of the 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"
   ]
  }
 ],
 "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.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
