{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5841d5c6-8ade-4e90-9134-a56f0b1faace",
   "metadata": {},
   "source": [
    "## Lecture 14, 23 September 2025"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec9c6118-242c-4572-bfe9-caceaa4db493",
   "metadata": {},
   "source": [
    "### Default values for function parameters\n",
    "- Can provide a default value for a parameter\n",
    "- If no argument is passed, default value is used\n",
    "- Recall `int(s)` converts a string `s` into an `int` if it makes sense"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d4ef37a1-af0a-4830-9319-513138106b62",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int(\"7\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "064b9b0b-525c-49a7-99bd-0a32d92f75a2",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "invalid literal for int() with base 10: 'AB'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mValueError\u001b[39m                                Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mAB\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "\u001b[31mValueError\u001b[39m: invalid literal for int() with base 10: 'AB'"
     ]
    }
   ],
   "source": [
    "int(\"AB\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d214542-c606-4fc3-ba02-0ac4eefb74cb",
   "metadata": {},
   "source": [
    "- The error message above refers to `base 10`\n",
    "- `int()` has an optional second parameter, which is the base\n",
    "- If we specify base 16, the previous conversion works"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "9bfd9cef-3a67-4191-b9ad-7de7b0317d1c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "171"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int(\"AB\",16)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "127e553e-6b10-42fc-b2a1-28675af78dd4",
   "metadata": {},
   "source": [
    "- The way such a function is defined is as follows\n",
    "```\n",
    "def int(s,b=10):\n",
    "   ....\n",
    "```\n",
    "- If we call this function with only one argument, the default value of `b` is used, so the conversion is in base 10\n",
    "- If we pass two arguments, the second value is used to set `b`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41fef202-59b0-4d1f-9c37-2ce08cb8e1ce",
   "metadata": {},
   "source": [
    "- Here is another example, to illustrate the point"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7cecaea3-0d3c-4347-b516-e4577cf65d95",
   "metadata": {},
   "outputs": [],
   "source": [
    "def checkdef(x = 0, y = 0):\n",
    "    print(\"x:\",x,\"y:\",y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "fbb896e9-5f7b-4eda-8de9-52dc5c37d3b4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x: 0 y: 0\n"
     ]
    }
   ],
   "source": [
    "checkdef()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "efd71bc4-08a3-42d6-a0c4-e48d021eb769",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x: 7 y: 0\n"
     ]
    }
   ],
   "source": [
    "checkdef(7)  # 7 is used for the first parameter x, y gets the default value"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "690fdfc6-b7a2-499f-8b67-0b28a29b1921",
   "metadata": {},
   "source": [
    "- We can also pass parameters by name, ignoring the order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "cd82f198-a4cf-4f8a-a8b0-44cc23f4b7e2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x: 12 y: 17\n"
     ]
    }
   ],
   "source": [
    "checkdef(y=17,x=12)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "410524ef-0457-406e-9987-6a497c3d7d66",
   "metadata": {},
   "source": [
    "- Using this, we can pass an argument for `y` and use the default `x`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "85f0b5ec-f7d9-4c87-ab18-d46824e8e543",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x: 0 y: 9\n"
     ]
    }
   ],
   "source": [
    "checkdef(y=9)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecf45723-ddfe-47ab-9bcd-cbe3fcaee77e",
   "metadata": {},
   "source": [
    "### Defining our own data structures\n",
    "- Earlier, we implemented a \"linked\" list using dictionaries\n",
    "- The fundamental functions like `listappend`, `listinsert`, `listdelete` modify the underlying list\n",
    "- Instead of `mylist = {}`, we wrote `mylist = createlist()`\n",
    "- To check empty list, use a function `isempty()` rather than `mylist == {}`\n",
    "- Can we clearly separate the **interface** from the **implementation**?\n",
    "- Define the data structure in a more \"modular\" way"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e0c8275-654d-49cc-8de5-3001763bfdc0",
   "metadata": {},
   "source": [
    "### Object oriented approach\n",
    "- Describe a datatype using a template, called a **class**\n",
    "- Create independent instances of a class, each is an **object**\n",
    "- Each object has its own internal *state* -- the values of its local variables\n",
    "- All objects in a class share the same functions to query/update their state\n",
    "- `l.append(x)` vs `append(l,x)`\n",
    "  - Tell an object what to do vs passing an object to a function\n",
    "- Each object has a way to refer to itself"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7ae0e73-8848-44e1-846e-7281f728eee9",
   "metadata": {},
   "source": [
    "### Basic definition of class `Point` using $(x,y)$ coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8765b068-476a-42bf-9371-bc33d5e87e67",
   "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  # Same as self.x = self.x + deltax\n",
    "    # In general, if we have a = a op b for any arithmetic operation op, can write a op= b\n",
    "    # For example: a += 5 is a = a + 5, a -= 10 is a = a - 10 etc\n",
    "    self.y += deltay\n",
    "    # No return is same as empty return: return()\n",
    "    \n",
    "  def odistance(self):\n",
    "    import math\n",
    "    d = math.sqrt(self.x*self.x +\n",
    "                  self.y*self.y)\n",
    "    return(d)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1825f086-58f7-4355-a6d1-33b438957b6a",
   "metadata": {},
   "source": [
    "Create two points"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6ac82308-9595-43ab-b9e3-770af468af4a",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca486b17-4845-4662-b5e2-c3d50f99a60a",
   "metadata": {},
   "source": [
    "Compute `odistance()` for `p` and `q`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "05b37537-5b96-4eab-919f-62ba1ba7ca5a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5.0, 12.206555615733702)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.odistance(), q.odistance()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "645c0179-5878-4619-b959-6bb3ed10019a",
   "metadata": {},
   "source": [
    "Translate `p` and check the distance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8c0667c2-847a-4aaf-9e13-b776f7fc9706",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.translate(3,4)\n",
    "p.odistance()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87c77a81-abeb-4dd3-85d1-d5f1ad7da7c1",
   "metadata": {},
   "source": [
    "* At this stage, `print()` does not produce anything meaningful\n",
    "* `+` is not defined yet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "cee6d476-9333-4d8b-b3d5-8ec198b3e0e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<__main__.Point object at 0x7fa88dcf17f0>\n"
     ]
    }
   ],
   "source": [
    "print(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b2b5db14-b7cc-4b2f-b511-e962c78ae63a",
   "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[14]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[43mp\u001b[49m\u001b[43m+\u001b[49m\u001b[43mq\u001b[49m)\n",
      "\u001b[31mTypeError\u001b[39m: unsupported operand type(s) for +: 'Point' and 'Point'"
     ]
    }
   ],
   "source": [
    "print(p+q)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94603a4f-3465-48b7-8821-92eba5ee11b7",
   "metadata": {},
   "source": [
    "- Use special functions to make these possible\n",
    "- `print()` requires converting its argument to a string\n",
    "    - Function `__str__()` specifies how to do this\n",
    "- `+` implicitly calls `__add__()`\n",
    "    - `p + q` gets translated as `p.__add__(q)`\n",
    "    - `q + p` gets translated as `q.__add__(p)`\n",
    "    - In either case, `__add__()` is executed in the context of one point and the other point is passed to it as an argument\n",
    "    - We will define `__add__()` so that it returns a new `Point` without modifying its arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "c280b93a-ec4c-4b65-a442-55bbd40f039b",
   "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):\n",
    "    return(Point(self.x + p.x, \n",
    "                 self.y + p.y))\n",
    "  # Previous line is a concise way of saying\n",
    "  #\n",
    "  # newx = self.x + p.x\n",
    "  # newy = self.y + p.y\n",
    "  # newpt = Point(newx,newy)\n",
    "  # return(newpt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "4b49ef1e-a0c8-4fd4-8e6d-fc5bf63a17f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a40b412a-a6b7-42f4-9ee1-3e7e86ff4607",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5.0, 12.206555615733702)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.odistance(), q.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "519f9022-b62a-4bcc-94a6-4ecb2342f6d5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.translate(3,4)\n",
    "p.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "b50b1819-5551-4573-bd7d-6b79085ca869",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6,8)\n"
     ]
    }
   ],
   "source": [
    "print(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "da02deb7-b790-4f51-adf0-dbd711d6161b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(6,8)'"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "85dd3dbc-bfce-46a4-bb0f-a5a22106b4e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(13,18)\n"
     ]
    }
   ],
   "source": [
    "print(p+q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "f7f7db55-5dd7-4691-84f7-b4ae603b9e28",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6,8) (7,10)\n"
     ]
    }
   ],
   "source": [
    "print(p,q)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "523f511e-b8c4-4405-a9d2-16c643db9eb5",
   "metadata": {},
   "source": [
    "- What if we want to compare two points?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "c19baaf1-5dfd-4d2b-902c-dc3e6c119da7",
   "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[23]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mp\u001b[49m\u001b[43m \u001b[49m\u001b[43m<\u001b[49m\u001b[43m \u001b[49m\u001b[43mq\u001b[49m\n",
      "\u001b[31mTypeError\u001b[39m: '<' not supported between instances of 'Point' and 'Point'"
     ]
    }
   ],
   "source": [
    "p < q"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "905d69fc-c3ad-4992-8b0d-6c073f75a4a8",
   "metadata": {},
   "source": [
    "- `<` is mapped to a function `__lt__()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "635b033d-f33e-40f5-96ff-fa038b8d565d",
   "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):\n",
    "    return(Point(self.x + p.x, \n",
    "                 self.y + p.y))\n",
    "\n",
    "  def __lt__(self,p):\n",
    "    return(self.x < p.x and self.y < p.y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "31246f50-4e57-4847-917a-054b2b268856",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "959babbf-d1d6-4e2c-ba1b-1beaa8e47eb7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False)"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p < q, q < p"
   ]
  }
 ],
 "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
}
