{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5841d5c6-8ade-4e90-9134-a56f0b1faace",
   "metadata": {},
   "source": [
    "## Lecture 14, 6 October 2026"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7ae0e73-8848-44e1-846e-7281f728eee9",
   "metadata": {},
   "source": [
    "### Class `Point` using $(x,y)$ coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "635b033d-f33e-40f5-96ff-fa038b8d565d",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Point:\n",
    "  def __init__(self,a=0,b=0): # Constructor\n",
    "    self.x = a\n",
    "    self.y = b\n",
    "\n",
    "  def translate(self,deltax,deltay):\n",
    "    self.x += deltax  # Short for self.x = self.x + deltax\n",
    "    self.y += deltay\n",
    "\n",
    "  def odistance(self):\n",
    "    import math\n",
    "    d = math.sqrt(self.x*self.x +\n",
    "                  self.y*self.y)\n",
    "    return(d)\n",
    "\n",
    "  def __str__(self):\n",
    "    return('('+str(self.x)+','\n",
    "            +str(self.y)+')')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "31246f50-4e57-4847-917a-054b2b268856",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)\n",
    "r = Point(3,4)\n",
    "s = Point(7,11)\n",
    "t = Point()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e14cb1ff-e8b2-4b29-b559-96e76636fe08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<__main__.Point at 0x7f6651354980>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "2ecfbe3a-ce38-40b3-ba4f-e5e61a6b2b47",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3,4)\n"
     ]
    }
   ],
   "source": [
    "print(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "5ccf6d7a-d37c-4722-a210-7b36a034c026",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(3,4)'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f45d94ee-aafb-416c-a564-7ef59d5d9874",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0,0)\n"
     ]
    }
   ],
   "source": [
    "print(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "bc21612c-2133-49c8-9223-6336ab188762",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "8241a0f5-d460-45e3-bb8f-25a34e99f935",
   "metadata": {},
   "outputs": [],
   "source": [
    "q.translate(-1,-2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "06a3cbed-9f25-4355-9e07-ccb8fa1263b7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(6,8)'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e9bbdf8c-dd02-4382-941f-9a2df4db319d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1 = [1,2,3]\n",
    "l2 = [1,2,3]\n",
    "l1 == l2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8ae8ba3a-03ad-4736-a811-bc9f4ba064ad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1 is l2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a4b75dba-0876-4af7-bad5-f541634c4041",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p == r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "959babbf-d1d6-4e2c-ba1b-1beaa8e47eb7",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'<=' not supported between instances of 'Point' and 'Point'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mTypeError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[13]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m p <= q\n",
      "\u001b[31mTypeError\u001b[39m: '<=' not supported between instances of 'Point' and 'Point'"
     ]
    }
   ],
   "source": [
    "p <= q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b041041a-5142-46b3-a066-ab1fbc22f24c",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Point:\n",
    "  def __init__(self,a=0,b=0):\n",
    "    self.x = a\n",
    "    self.y = b\n",
    "\n",
    "  def translate(self,deltax,deltay):\n",
    "    self.x += deltax\n",
    "    self.y += deltay\n",
    "\n",
    "  def odistance(self):\n",
    "    import math\n",
    "    d = math.sqrt(self.x*self.x +\n",
    "                  self.y*self.y)\n",
    "    return(d)\n",
    "\n",
    "  def __str__(self):\n",
    "    return('('+str(self.x)+','\n",
    "            +str(self.y)+')')\n",
    "\n",
    "  def __add__(self,p):    # Create a new Point(x1+x2,y1+y2)\n",
    "    return(Point(self.x + p.x,     # Short for newp = Point(..), return (newp)\n",
    "                 self.y + p.y))\n",
    "\n",
    "  def __lt__(self,p):\n",
    "    return(self.x < p.x and self.y < p.y)\n",
    "\n",
    "  def __le__(self,p):\n",
    "    return(self.x <= p.x and self.y <= p.y)\n",
    "      \n",
    "  def __eq__(self,p):\n",
    "    return(self.x == p.x and self.y == p.y)\n",
    "\n",
    "  def __ne__(self,p):\n",
    "    return(not(self == p))\n",
    "\n",
    "  def __gt__(self,p):\n",
    "    return(self.x > p.x and self.y > p.y)\n",
    "\n",
    "  def __ge__(self,p):\n",
    "    return(self.x >= p.x and self.y >= p.y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2bb83c65-04d3-422e-af89-141c68e4e617",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)\n",
    "r = Point(3,4)\n",
    "s = Point(7,11)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7901b443-2fa0-475f-95b4-19499831f276",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False, False, True, True, True, True, True)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p < q, q < p, p == q, p == r, p <= p, q <= s, s >= q, q > p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "324b3f45-0a04-4adf-ae16-19f7ce66ea70",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(10,15)'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p+s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "e9382dee-23a6-42f7-9050-85ebf451b508",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(13,19)'"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p+s+r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "8658c569-87bc-4f53-bdbe-2ae1b606c846",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unsupported operand type(s) for -: 'Point' and 'Point'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mTypeError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[19]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m str(p-s)\n",
      "\u001b[31mTypeError\u001b[39m: unsupported operand type(s) for -: 'Point' and 'Point'"
     ]
    }
   ],
   "source": [
    "str(p-s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "3717f9a5-00b6-45f1-910a-b4ede404bb1d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p is r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0ebf4d78-9709-4b2e-a913-710c30fa2b92",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "afd26bbc-ffb9-4bd3-b155-b7183b5c1549",
   "metadata": {},
   "outputs": [],
   "source": [
    "t.translate(3,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "17c7ef21-b0ab-42c0-ac76-95ad48b355dc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6,8)\n"
     ]
    }
   ],
   "source": [
    "print(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "bf38b1c2-1421-496f-b3cd-fd174f8ec29b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p is t"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba743337-4afe-4c6d-b612-c0ae5d524cec",
   "metadata": {},
   "source": [
    "### Changing the implementation\n",
    "- Change the definition of Point to use polar representation, $(r,\\theta)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "d72b8d18-48fc-41c8-b0f8-c4ce3de9187c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "class Point:\n",
    "  def __init__(self,a=0,b=0):\n",
    "    self.r = math.sqrt(a*a + b*b)\n",
    "    if a == 0:\n",
    "      if b >= 0:\n",
    "        self.theta = math.pi/2\n",
    "      else:\n",
    "        self.theta = 3*math.pi/2\n",
    "    else:\n",
    "      self.theta = math.atan(b/a)\n",
    "\n",
    "  def translate(self,deltax,deltay):    \n",
    "    x = self.r*math.cos(self.theta)\n",
    "    y = self.r*math.sin(self.theta)\n",
    "    x += deltax\n",
    "    y += deltay\n",
    "    self.r = math.sqrt(x*x + y*y)\n",
    "    if x == 0:\n",
    "      if y >= 0:\n",
    "        self.theta = math.pi/2\n",
    "      else:\n",
    "        self.theta = 3*math.pi/2\n",
    "    else:\n",
    "      self.theta = math.atan(y/x)\n",
    "\n",
    "  def odistance(self):\n",
    "    return(self.r)\n",
    "\n",
    "  def __str__(self):\n",
    "    x = self.r*math.cos(self.theta)\n",
    "    y = self.r*math.sin(self.theta)\n",
    "    return('('+str(x)+','+str(y)+')')\n",
    "\n",
    "  def __add__(self,p):\n",
    "    sx = self.r*math.cos(self.theta)\n",
    "    sy = self.r*math.sin(self.theta)\n",
    "    px = p.r*math.cos(p.theta)\n",
    "    py = p.r*math.sin(p.theta)\n",
    "    return(Point(sx + px,sy+py))\n",
    "\n",
    "  def __lt__(self,p):\n",
    "    sx = self.r*math.cos(self.theta)\n",
    "    sy = self.r*math.sin(self.theta)\n",
    "    px = p.r*math.cos(p.theta)\n",
    "    py = p.r*math.sin(p.theta)\n",
    "    return(sx < px and sy < py)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45bb3fed-5f3c-4a02-beac-7390a9679cc0",
   "metadata": {},
   "source": [
    "- The interface still assumes $(x,y)$ representation\n",
    "- When constructing a point, convert $(x,y)$ to $(r,\\theta)$\n",
    "    - Be careful about the case where $x = 0$\n",
    "- To translate a point, convert $(r,\\theta)$ back to $(x,y)$, translate, then convert back to $(r,\\theta)$\n",
    "- Similar conversion for `__str__()`, `__add__()`, `__lt__()`\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0e6c208-6c89-4bc5-9a67-21696f2d37a6",
   "metadata": {},
   "source": [
    "### Repeat the examples above\n",
    "* Observe that nothing changes for the user of the class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "15ff17ab-229a-4720-9393-0b2f0b4ebecb",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "1587da6e-0f62-4fef-a4ad-c578a3669df1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5.0, 12.206555615733702)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.odistance(), q.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "ca919c89-b46e-4e3d-ba10-06f3e4bdeedb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.translate(3,4)\n",
    "p.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "858bffa2-1008-491b-bc6d-89a48c692ca5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6.000000000000001,7.999999999999999)\n"
     ]
    }
   ],
   "source": [
    "print(p) # Note some lack of precision going from (x,y) to (r,theta) and back"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "7ea9c512-dfb8-494f-b847-41a4b5e616b8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(6.000000000000001,7.999999999999999)'"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "5b8a1a6c-07de-4c97-ad24-0748ae8366f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(13.000000000000002,18.0)\n"
     ]
    }
   ],
   "source": [
    "print(p+q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "766be397-6409-4ff5-bf7e-da21c40c2f48",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6.000000000000001,7.999999999999999) (6.999999999999999,10.0)\n"
     ]
    }
   ],
   "source": [
    "print(p,q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "10c63d92-1862-4f5e-8bd3-7a28df6acb7c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p < q, q < p"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8d5a98d-5fcf-4d65-81f3-2b3e9dbbd048",
   "metadata": {},
   "source": [
    "#### A note about variables inside classes\n",
    "- Without the prefix `self`, variables are internal to a function\n",
    "- Variables with prefix `self` persist within the object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "adc1c4e7-680a-4235-a295-97f0dba9e047",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment:\n",
    "    def __init__(self,a):\n",
    "        x = a\n",
    "        \n",
    "    def __str__(self):\n",
    "        return(str(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "caaff9b8-6e2c-4c98-a232-49735f29bbf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "z = Experiment(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "f222462c-57b1-49a4-8bbf-bf077fb8270e",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'x' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNameError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[36]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m str(z)\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[34]\u001b[39m\u001b[32m, line 6\u001b[39m, in \u001b[36mExperiment.__str__\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m      5\u001b[39m     \u001b[38;5;28;01mdef\u001b[39;00m __str__(self):\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m         \u001b[38;5;28;01mreturn\u001b[39;00m(str(x))\n",
      "\u001b[31mNameError\u001b[39m: name 'x' is not defined"
     ]
    }
   ],
   "source": [
    "str(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "0c6bde24-5014-4dcb-ac3d-a8e186b3ccc9",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment2:\n",
    "    def __init__(self,a):\n",
    "        self.x = a\n",
    "        \n",
    "    def __str__(self):\n",
    "        return(str(self.x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "22ebcb7e-34d3-4cff-a612-92638cacfc10",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'7'"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = Experiment2(7)\n",
    "str(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3e80b95-cfd9-402e-a293-0843eb1fe3b6",
   "metadata": {},
   "source": [
    "- The name `self` for the current object (first parameter) is only a convention\n",
    "- Can use any other name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "5506a2a1-425e-4365-bd18-1671f26c347e",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment3:\n",
    "    def __init__(self,a):\n",
    "        self.x = a\n",
    "        \n",
    "    def __str__(this):\n",
    "        return(str(this.x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "7f50d6f0-f689-4830-824c-d413c3e92052",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17\n"
     ]
    }
   ],
   "source": [
    "x = Experiment3(17)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a600a37-8aed-43c0-be29-173ec9acb27f",
   "metadata": {},
   "source": [
    "- Classes and objects were grafted onto Python as an afterthought\n",
    "- If we have a class `C`, and object `O` and a function `f(self,x,y,z)` inside `C`, we can replace `o.f(a,b,c)` by `C.f(o,a,b,c)`.\n",
    "- In other words, `self` is actually a reference to the object on which `f` is being invoked."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "6c586c29-3b6b-435d-beb1-ce7fb5a7292f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8.602325267042627"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pnew = Point(5,7)\n",
    "pnew.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "66379da1-2855-4b1e-aa8d-c73672f17de1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8.602325267042627"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Point.odistance(pnew)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "0c962b28-7a1b-4306-8a9c-e6d9cb395e29",
   "metadata": {},
   "outputs": [],
   "source": [
    "Point.translate(pnew,4,7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "a9d2b1f0-182d-4415-9525-52da153ca668",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(9.0,14.0)\n"
     ]
    }
   ],
   "source": [
    "print(pnew)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "720f971f-feb3-4420-a152-fce4ef626787",
   "metadata": {},
   "source": [
    "- This is also true for built in datatypes like `list`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "276ded1e-2a04-478c-b295-047bb3a7849f",
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1,2,3]\n",
    "l.append(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "d682aced-3129-4424-92b4-9de1622c8911",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "7c9217d3-ca7a-45be-b547-c5ce41694705",
   "metadata": {},
   "outputs": [],
   "source": [
    "list.append(l,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "56589860-5782-4690-802f-4de9f88b6536",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4, 5]"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b7a1cc1-153b-47b5-996f-de4a6b3979b5",
   "metadata": {},
   "source": [
    "- Python also has no mechanism to ensure privacy of implementation\n",
    "- We cannot prevent code outside the class from accessing internal fields `p.x` and `p.y` for a `Point` `p`\n",
    "- In fact, we can even add new internal fields!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "6f5ac3e8-a9b4-432c-9391-1777a2413474",
   "metadata": {},
   "outputs": [],
   "source": [
    "pnew.z = 7"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a8115d2",
   "metadata": {},
   "source": [
    "### Linked lists"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a7bdc56-97fd-4689-8462-d0382254c1df",
   "metadata": {},
   "source": [
    "- An implementation using classes and objects; compare with our earlier implementation using nested dictionaries\n",
    "- An empty list has a single node with `value` and `next` both `None`\n",
    "- Last node in the list has `next` set to `None`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "1fe19866",
   "metadata": {},
   "outputs": [],
   "source": [
    "class List:\n",
    "    def __init__(self):\n",
    "        self.value = None\n",
    "        self.next = None\n",
    "        return\n",
    "\n",
    "    def isempty(self):\n",
    "        return(self.value == None)\n",
    "    \n",
    "    def append(self,v):   # append, iterative\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "            return\n",
    "        \n",
    "        temp = self\n",
    "        while temp.next != None:\n",
    "            temp = temp.next\n",
    "\n",
    "        temp.next = List()\n",
    "        temp.next.value = v \n",
    "        return   \n",
    "\n",
    "    def insert(self,v):\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "            return\n",
    "\n",
    "        newnode = List()\n",
    "        newnode.value = v\n",
    "        \n",
    "        # Exchange values in self and newnode\n",
    "        (self.value, newnode.value) = (newnode.value, self.value)\n",
    "\n",
    "        # Switch links\n",
    "        (self.next, newnode.next) = (newnode, self.next)\n",
    "\n",
    "        return\n",
    "\n",
    "\n",
    "    def __str__(self):\n",
    "        # Iteratively create a Python list from linked list\n",
    "        # and convert that to a string\n",
    "        selflist = []\n",
    "        if self.isempty():\n",
    "            return(str(selflist))\n",
    "\n",
    "        temp = self\n",
    "        selflist.append(temp.value)\n",
    "        \n",
    "        while temp.next != None:\n",
    "          temp = temp.next\n",
    "          selflist.append(temp.value)\n",
    "\n",
    "        return(str(selflist))"
   ]
  }
 ],
 "metadata": {
  "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.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
