{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6b4fce18-128e-441d-9040-7d738b1ac1c8",
   "metadata": {},
   "source": [
    "## PDSP 2026, Lecture 09, 8 September 2026"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "90dd963d-bf0a-4fa5-963d-1f79a418243d",
   "metadata": {},
   "outputs": [],
   "source": [
    "matchlist = [\n",
    "  (\"Mexico City\",\"MEX\",\"RSA\",2,0,0,0,1.84,0.52),\n",
    "  (\"Zapopan\",\"KOR\",\"CZE\",2,1,0,0,1.45,1.12),\n",
    "  (\"Toronto\",\"CAN\",\"BIH\",1,1,0,0,1.35,0.98),\n",
    "  (\"Inglewood\",\"USA\",\"PAR\",4,1,0,0,2.76,0.88),\n",
    "  (\"Foxborough\",\"QAT\",\"SUI\",1,1,0,0,0.78,1.54),\n",
    "  (\"East Rutherford\",\"BRA\",\"MAR\",1,1,0,0,1.62,1.1),\n",
    "  (\"Philadelphia\",\"HAI\",\"SCO\",0,1,0,0,1.25,0.65),\n",
    "  (\"Seattle\",\"AUS\",\"TUR\",2,0,0,0,1.48,0.72),\n",
    "  (\"Atlanta\",\"GER\",\"CUW\",7,1,0,0,4.82,0.44),\n",
    "  (\"Santa Clara\",\"NED\",\"JPN\",2,2,0,0,1.95,1.82),\n",
    "  (\"Houston\",\"CIV\",\"ECU\",1,0,0,0,1.1,0.95),\n",
    "  (\"Kansas City\",\"SWE\",\"TUN\",5,1,0,0,3.12,0.78),\n",
    "  (\"Miami Gardens\",\"ESP\",\"CPV\",0,0,0,0,2.15,0.35),\n",
    "  (\"Arlington\",\"BEL\",\"EGY\",1,1,0,0,1.58,1.12),\n",
    "  (\"Guadalupe\",\"KSA\",\"URU\",1,1,0,0,0.85,1.76),\n",
    "  (\"Vancouver\",\"IRN\",\"NZL\",2,2,0,0,1.88,1.2),\n",
    "  (\"East Rutherford\",\"FRA\",\"SEN\",3,1,0,0,2.44,1.05),\n",
    "  (\"Foxborough\",\"IRQ\",\"NOR\",1,4,0,0,0.68,2.85),\n",
    "  (\"Inglewood\",\"ARG\",\"ALG\",3,0,0,0,2.65,0.42),\n",
    "  (\"Santa Clara\",\"AUT\",\"JOR\",3,1,0,0,1.98,0.88),\n",
    "  (\"Atlanta\",\"POR\",\"COD\",1,1,0,0,1.78,1.15),\n",
    "  (\"Miami Gardens\",\"ENG\",\"CRO\",4,2,0,0,2.92,1.64),\n",
    "  (\"Houston\",\"GHA\",\"PAN\",1,0,0,0,1.3,0.75),\n",
    "  (\"Seattle\",\"UZB\",\"COL\",1,3,0,0,0.95,2.1),\n",
    "  (\"Atlanta\",\"MEX\",\"KOR\",1,0,0,0,1.62,0.58),\n",
    "  (\"Inglewood\",\"CZE\",\"RSA\",1,1,0,0,1.35,1.15),\n",
    "  (\"Vancouver\",\"CAN\",\"QAT\",6,0,0,0,3.82,0.22),\n",
    "  (\"Mexico City\",\"SUI\",\"BIH\",4,1,0,0,2.45,0.88),\n",
    "  (\"East Rutherford\",\"BRA\",\"HAI\",3,0,0,0,1.16,0.9),\n",
    "  (\"Arlington\",\"SCO\",\"MAR\",0,1,0,0,0.97,0.54),\n",
    "  (\"Toronto\",\"USA\",\"AUS\",2,0,0,0,1.21,0.32),\n",
    "  (\"Guadalupe\",\"TUR\",\"PAR\",0,1,0,0,0.4,0.3),\n",
    "  (\"Foxborough\",\"GER\",\"CIV\",2,1,0,0,1.85,0.72),\n",
    "  (\"Kansas City\",\"ECU\",\"CUW\",0,0,0,0,1.92,0.08),\n",
    "  (\"Philadelphia\",\"NED\",\"SWE\",5,1,0,0,3.45,0.88),\n",
    "  (\"Seattle\",\"TUN\",\"JPN\",0,4,0,0,0.35,3.12),\n",
    "  (\"Houston\",\"BEL\",\"IRN\",0,0,0,0,1.45,0.62),\n",
    "  (\"Miami Gardens\",\"NZL\",\"EGY\",1,3,0,0,0.55,2.15),\n",
    "  (\"Santa Clara\",\"ESP\",\"KSA\",4,0,0,0,3.28,0.25),\n",
    "  (\"East Rutherford\",\"URU\",\"CPV\",2,2,0,0,1.65,1.1),\n",
    "  (\"Arlington\",\"FRA\",\"IRQ\",3,0,0,0,2.21,0.45),\n",
    "  (\"Toronto\",\"NOR\",\"SEN\",3,2,0,0,1.95,1.48),\n",
    "  (\"Guadalupe\",\"ARG\",\"AUT\",2,0,0,0,1.78,0.55),\n",
    "  (\"Foxborough\",\"JOR\",\"ALG\",1,2,0,0,0.88,1.92),\n",
    "  (\"Kansas City\",\"POR\",\"UZB\",5,0,0,0,3.54,0.42),\n",
    "  (\"Philadelphia\",\"COL\",\"COD\",1,0,0,0,1.62,0.58),\n",
    "  (\"Seattle\",\"ENG\",\"GHA\",0,0,0,0,1.12,0.89),\n",
    "  (\"Mexico City\",\"PAN\",\"CRO\",0,1,0,0,0.42,1.48),\n",
    "  (\"Mexico City\",\"CZE\",\"MEX\",0,3,0,0,1.1,1.27),\n",
    "  (\"Zapopan\",\"RSA\",\"KOR\",1,0,0,0,1.26,1.39),\n",
    "  (\"Vancouver\",\"SUI\",\"CAN\",2,1,0,0,0.71,1.35),\n",
    "  (\"Toronto\",\"BIH\",\"QAT\",3,1,0,0,1.48,0.95),\n",
    "  (\"East Rutherford\",\"SCO\",\"BRA\",0,3,0,0,0.45,2.18),\n",
    "  (\"Foxborough\",\"MAR\",\"HAI\",4,2,0,0,2.35,1.12),\n",
    "  (\"Inglewood\",\"TUR\",\"USA\",3,2,0,0,1.62,1.45),\n",
    "  (\"Santa Clara\",\"PAR\",\"AUS\",0,0,0,0,0.55,0.48),\n",
    "  (\"Atlanta\",\"ECU\",\"GER\",2,1,0,0,1.28,1.55),\n",
    "  (\"Houston\",\"CUW\",\"CIV\",0,2,0,0,0.32,1.68),\n",
    "  (\"Kansas City\",\"TUN\",\"NED\",1,3,0,0,0.62,2.15),\n",
    "  (\"Seattle\",\"JPN\",\"SWE\",1,1,0,0,1.12,0.95),\n",
    "  (\"Arlington\",\"NZL\",\"BEL\",1,5,0,0,0.48,3.25),\n",
    "  (\"Guadalupe\",\"EGY\",\"IRN\",1,1,0,0,0.85,0.92),\n",
    "  (\"Miami Gardens\",\"URU\",\"ESP\",0,1,0,0,0.78,1.35),\n",
    "  (\"Philadelphia\",\"CPV\",\"KSA\",0,0,0,0,0.42,0.38),\n",
    "  (\"Foxborough\",\"NOR\",\"FRA\",1,4,0,0,1.3,0.96),\n",
    "  (\"East Rutherford\",\"SEN\",\"IRQ\",5,0,0,0,3.01,0.14),\n",
    "  (\"Santa Clara\",\"JOR\",\"ARG\",1,3,0,0,0.76,2.13),\n",
    "  (\"Inglewood\",\"ALG\",\"AUT\",3,3,0,0,1.62,1.44),\n",
    "  (\"Miami Gardens\",\"COL\",\"POR\",0,0,0,0,1.62,0.73),\n",
    "  (\"Atlanta\",\"COD\",\"UZB\",3,1,0,0,2.35,0.2),\n",
    "  (\"East Rutherford\",\"PAN\",\"ENG\",0,2,0,0,0.69,1.39),\n",
    "  (\"Philadelphia\",\"CRO\",\"GHA\",2,1,0,0,0.42,0.74),\n",
    "  (\"Inglewood\",\"RSA\",\"CAN\",0,1,0,0,0.13,1.32),\n",
    "  (\"Houston\",\"BRA\",\"JPN\",2,1,0,0,1.69,0.23),\n",
    "  (\"Foxborough\",\"GER\",\"PAR\",1,1,3,4,0.72,0.42),\n",
    "  (\"Guadalupe\",\"NED\",\"MAR\",1,1,2,3,0.23,1.4),\n",
    "  (\"Arlington\",\"CIV\",\"NOR\",1,2,0,0,1.15,2.02),\n",
    "  (\"East Rutherford\",\"FRA\",\"SWE\",3,0,0,0,3.17,0.67),\n",
    "  (\"Mexico City\",\"MEX\",\"ECU\",2,0,0,0,1.02,0.73),\n",
    "  (\"Atlanta\",\"ENG\",\"COD\",2,1,0,0,2.04,0.76),\n",
    "  (\"Seattle\",\"BEL\",\"SEN\",3,2,0,0,1.74,3.58),\n",
    "  (\"Santa Clara\",\"USA\",\"BIH\",2,0,0,0,0.92,0.25),\n",
    "  (\"Inglewood\",\"ESP\",\"AUT\",3,0,0,0,2.84,0.32),\n",
    "  (\"Toronto\",\"POR\",\"CRO\",2,1,0,0,2.18,1.34),\n",
    "  (\"Vancouver\",\"SUI\",\"ALG\",2,0,0,0,2.52,0.73),\n",
    "  (\"Arlington\",\"AUS\",\"EGY\",1,1,2,4,0.87,1.36),\n",
    "  (\"Miami Gardens\",\"ARG\",\"CPV\",3,2,0,0,2.16,0.46),\n",
    "  (\"Kansas City\",\"COL\",\"GHA\",1,0,0,0,2.19,0.26),\n",
    "  (\"Philadelphia\",\"PAR\",\"FRA\",0,1,0,0,0.3,1.8),\n",
    "  (\"Houston\",\"CAN\",\"MAR\",0,3,0,0,0.8,1.2),\n",
    "  (\"Arlington\",\"BRA\",\"NOR\",1,2,0,0,2.61,1.05),\n",
    "  (\"Mexico City\",\"MEX\",\"ENG\",2,3,0,0,1.88,1.61),\n",
    "  (\"Miami Gardens\",\"POR\",\"ESP\",0,1,0,0,0.63,1.69),\n",
    "  (\"Santa Clara\",\"USA\",\"BEL\",1,4,0,0,0.67,2.15),\n",
    "  (\"Kansas City\",\"ARG\",\"EGY\",3,2,0,0,2.12,1.54),\n",
    "  (\"Seattle\",\"SUI\",\"COL\",0,0,4,3,1.15,1.46),\n",
    "  (\"Foxborough\",\"FRA\",\"MAR\",2,0,0,0,3.1,0.13),\n",
    "  (\"Inglewood\",\"ESP\",\"BEL\",2,1,0,0,2.08,0.37),\n",
    "  (\"Miami Gardens\",\"NOR\",\"ENG\",1,2,0,0,0.77,0.96),\n",
    "  (\"Kansas City\",\"ARG\",\"SUI\",3,1,0,0,2.0,0.53),\n",
    "  (\"Arlington\",\"FRA\",\"ESP\",0,2,0,0,0.3,1.63),\n",
    "  (\"Atlanta\",\"ENG\",\"ARG\",1,2,0,0,0.54,1.80),\n",
    "  (\"Miami Gardens\",\"FRA\",\"ENG\",4,6,0,0,2.88,2.88),\n",
    "  (\"East Rutherford\",\"ESP\",\"ARG\",1,0,0,0,0.52,0.09)\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e3c85b87-4a79-447b-9c1d-7309d5029bb7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def expand(s):\n",
    "    teamdict = {\n",
    "        'ALG':'Algeria',\n",
    "        'ARG':'Argentina',\n",
    "        'AUS':'Australia',\n",
    "        'AUT':'Austria',\n",
    "        'BEL':'Belgium',\n",
    "        'BIH':'Bosnia Herzegovina',\n",
    "        'BRA':'Brazil',\n",
    "        'CAN':'Canada',\n",
    "        'CIV':'Ivory Coast',\n",
    "        'COD':'Congo',\n",
    "        'COL':'Colombia',\n",
    "        'CPV':'Cape Verde',\n",
    "        'CRO':'Croatia',\n",
    "        'CUW':'Curacao',\n",
    "        'CZE':'Czech Republic',\n",
    "        'ECU':'Ecuador',\n",
    "        'EGY':'Egypt',\n",
    "        'ENG':'England',\n",
    "        'ESP':'Spain',\n",
    "        'FRA':'France',\n",
    "        'GER':'Germany',\n",
    "        'GHA':'Ghana',\n",
    "        'HAI':'Haiti',\n",
    "        'IRN':'Iran',\n",
    "        'IRQ':'Iraq',\n",
    "        'JOR':'Jordan',\n",
    "        'JPN':'Japan',\n",
    "        'KOR':'Korea',\n",
    "        'KSA':'Saudi Arabia',\n",
    "        'MAR':'Morocco',\n",
    "        'MEX':'Mexico',\n",
    "        'NED':'Netherlands',\n",
    "        'NOR':'Norway',\n",
    "        'NZL':'New Zealand',\n",
    "        'PAN':'Panama',\n",
    "        'PAR':'Paraguay',\n",
    "        'POR':'Portugal',\n",
    "        'QAT':'Qatar',\n",
    "        'RSA':'South Africa',\n",
    "        'SCO':'Scotland',\n",
    "        'SEN':'Senegal',\n",
    "        'SUI':'Switzerland',\n",
    "        'SWE':'Sweden',\n",
    "        'TUN':'Tunisia',\n",
    "        'TUR':'Turkey',\n",
    "        'URU':'Uruguay',\n",
    "        'USA':'United States of America',\n",
    "        'UZB':'Uzbekistan'}\n",
    "    if (s in teamdict):\n",
    "        return(teamdict[s])\n",
    "    else:\n",
    "        return('No info')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "178d9244-2567-4855-b1c2-ab26f3c70bf5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_teams(l):\n",
    "    teamdict = {}\n",
    "    for m in l:\n",
    "        team1,team2 = m[1],m[2]\n",
    "        teamdict[team1] = 1\n",
    "        teamdict[team2] = 2\n",
    "    return(sorted(list(teamdict)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "343843aa-5a0b-43ef-a08c-60983a2ad97c",
   "metadata": {},
   "source": [
    "## Map, filter, list comprehension"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e82f948-c993-4a3b-a292-e67f42fd4809",
   "metadata": {},
   "source": [
    "### Map\n",
    "- Apply a function $f()$ to each element in a list\n",
    "- Convert $[x_0,x_1,\\ldots,x_{n-1}]$ to $[f(x_0),f(x_1),\\ldots,f(x_{n-1})]$\n",
    "- In Python, `map(f,l)` applies `f` to each element of `l`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "98feffe9-0f64-4479-a05f-d910c58550e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def square(m):\n",
    "    return m*m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d331de50-38bf-4f69-af46-0bc64ea70c68",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 4, 9, 16, 25, 36]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(square,range(1,7)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a878ee4-04c5-4437-bc3c-335c63a83eba",
   "metadata": {},
   "source": [
    "### Filter\n",
    "- Extract items from a list that satisfy a property\n",
    "    - For instance, extract the even numbers from a list of numbers\n",
    "- A *property* is a function $p()$ that maps each input to `True` or `False\n",
    "    - Check if each item $x$ in a list satisfies a property $p(x)$\n",
    "    - Retain only such elements\n",
    "    - Filters out elements that do not satisfy $p()$\n",
    "- In Python, `filter(p,l)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "80dd835f-41ac-42d0-ba74-fcd177bf4650",
   "metadata": {},
   "outputs": [],
   "source": [
    "def even(m):\n",
    "    return m%2 == 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "15b9c621-7a44-442d-b789-2c8675f47f38",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(filter(even,range(1,7)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e3814e6-078c-4153-9ec8-eb692d224cfb",
   "metadata": {},
   "source": [
    "- Common to combine `map` and `filter`\n",
    "- Squares of even numbers in `[1,2,...,6]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "2dc6734f-9c00-4452-a778-2a9940acf981",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 16, 36]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(square,(filter(even,range(1,7)))))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e004e6ba-25fe-42a2-94c9-61995a40d59e",
   "metadata": {},
   "source": [
    "## List comprehension\n",
    "- Combine map and filter to create a list\n",
    "- *Set comprehension*: Squares of positive even integers = $\\{x^2 \\mid x \\in \\mathbb{Z}, x > 0, x \\bmod 2 = 0 \\}$\n",
    "- In Python: `[ f(x) for x in l if p(x) ]`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f101466-ca3c-42e8-9fae-6ae8ccc23fc6",
   "metadata": {},
   "source": [
    "- Using list comprehension to create a zero matrix"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b1f9e4b4-9c2d-4c0f-92da-9d363e9ca2ea",
   "metadata": {},
   "source": [
    "- First a row of `n` zeros"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8f741cba-8ea9-4b3d-b806-fa201d073336",
   "metadata": {},
   "outputs": [],
   "source": [
    "def zerorow(n):\n",
    "    return [0 for i in range(n)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f599b8cd-2a63-4450-8dec-87fc6ceda737",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 0, 0, 0, 0]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zerorow(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "326a828f-559d-4478-84ce-b643f16fd707",
   "metadata": {},
   "source": [
    "- Now, create a matrix with `n` distinct copies of `zerorow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fa859e41-94ff-4d6a-9826-f0bbf65e9d30",
   "metadata": {},
   "outputs": [],
   "source": [
    "def zeromat(n):\n",
    "    return [zerorow(n) for i in range(n)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c3630da9-97f2-4459-8928-05c33ae70b36",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0, 0, 0, 0, 0],\n",
       " [0, 0, 0, 0, 0],\n",
       " [0, 0, 0, 0, 0],\n",
       " [0, 0, 0, 0, 0],\n",
       " [0, 0, 0, 0, 0]]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zeromat(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "679ca18b-6b92-4576-846a-a5c92080fa3d",
   "metadata": {},
   "source": [
    "- Changing a diagonal entry does not affect the other rows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7cf6e9cf-920b-46c4-9e07-c1f073086931",
   "metadata": {},
   "outputs": [],
   "source": [
    "zm = zeromat(5)\n",
    "zm[2][2] = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d2731548-ef56-483a-8737-4c0aebcec16b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0, 0, 0, 0, 0],\n",
       " [0, 0, 0, 0, 0],\n",
       " [0, 0, 1, 0, 0],\n",
       " [0, 0, 0, 0, 0],\n",
       " [0, 0, 0, 0, 0]]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "248397b4-4ec5-4282-b960-a333bc52743f",
   "metadata": {},
   "source": [
    "- Create an identity matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "0e091e0a-365f-44c1-aef5-68d3192217e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def idmat(n):\n",
    "    zmat = zeromat(n)\n",
    "    for i in range(n):\n",
    "        zmat[i][i] = 1\n",
    "    return zmat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e2d44ed6-2910-4752-8925-7e16a58fa02f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1, 0, 0, 0, 0],\n",
       " [0, 1, 0, 0, 0],\n",
       " [0, 0, 1, 0, 0],\n",
       " [0, 0, 0, 1, 0],\n",
       " [0, 0, 0, 0, 1]]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "idmat(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c2fbaf9-0caf-4835-b639-6148ca667cf7",
   "metadata": {},
   "source": [
    "**Example**\n",
    "- Full names of all teams in FIFA 2026"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "1543189b-0130-48c5-9e09-419ee7aca93a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Algeria',\n",
       " 'Argentina',\n",
       " 'Australia',\n",
       " 'Austria',\n",
       " 'Belgium',\n",
       " 'Bosnia Herzegovina',\n",
       " 'Brazil',\n",
       " 'Canada',\n",
       " 'Ivory Coast',\n",
       " 'Congo',\n",
       " 'Colombia',\n",
       " 'Cape Verde',\n",
       " 'Croatia',\n",
       " 'Curacao',\n",
       " 'Czech Republic',\n",
       " 'Ecuador',\n",
       " 'Egypt',\n",
       " 'England',\n",
       " 'Spain',\n",
       " 'France',\n",
       " 'Germany',\n",
       " 'Ghana',\n",
       " 'Haiti',\n",
       " 'Iran',\n",
       " 'Iraq',\n",
       " 'Jordan',\n",
       " 'Japan',\n",
       " 'Korea',\n",
       " 'Saudi Arabia',\n",
       " 'Morocco',\n",
       " 'Mexico',\n",
       " 'Netherlands',\n",
       " 'Norway',\n",
       " 'New Zealand',\n",
       " 'Panama',\n",
       " 'Paraguay',\n",
       " 'Portugal',\n",
       " 'Qatar',\n",
       " 'South Africa',\n",
       " 'Scotland',\n",
       " 'Senegal',\n",
       " 'Switzerland',\n",
       " 'Sweden',\n",
       " 'Tunisia',\n",
       " 'Turkey',\n",
       " 'Uruguay',\n",
       " 'United States of America',\n",
       " 'Uzbekistan']"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ expand(t) for t in get_teams(matchlist) ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce7f1347-35c0-4103-b67d-e6cf2cb1d02a",
   "metadata": {},
   "source": [
    "- List both teams in matches where MEX was home team"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ce9a439-2df3-4066-b6ba-ac7a6ed8f393",
   "metadata": {},
   "source": [
    "- Equivalent of relational algebra selection and projection\n",
    "- Project matchlist onto columns `team 1, team 2` (columns 1,2) where MEX was home team\n",
    "    - Filter by MEX being home team\n",
    "    - Project onto columns 1,2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "01a10e11-e89e-453d-aaa2-940d1f80b929",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('Mexico City', 'MEX', 'RSA', 2, 0, 0, 0, 1.84, 0.52),\n",
       " ('Atlanta', 'MEX', 'KOR', 1, 0, 0, 0, 1.62, 0.58),\n",
       " ('Mexico City', 'MEX', 'ECU', 2, 0, 0, 0, 1.02, 0.73),\n",
       " ('Mexico City', 'MEX', 'ENG', 2, 3, 0, 0, 1.88, 1.61)]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ m for m in matchlist if m[1] == 'MEX' ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ebfe940d-0210-4d87-ba38-e691f4318153",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('MEX', 'RSA'), ('MEX', 'KOR'), ('MEX', 'ECU'), ('MEX', 'ENG')]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (m[1],m[2]) for m in matchlist if m[1] == 'MEX' ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4122f5f0-e516-4bb7-b071-365d18d2cebf",
   "metadata": {},
   "source": [
    "- Same, with full names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "0820f825",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('Mexico', 'South Africa'),\n",
       " ('Mexico', 'Korea'),\n",
       " ('Mexico', 'Ecuador'),\n",
       " ('Mexico', 'England')]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (expand(m[1]),expand(m[2])) for m in matchlist if m[1] == 'MEX' ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e286ff7-4038-4b0f-a5ea-ba3ddb34c8b1",
   "metadata": {},
   "source": [
    "- List comprehension notation can also be used to create dictionaries\n",
    "- Create a dictionary matching team abbreviations to full names for teams in FIFA 2026"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "209e78f1-6af5-448b-a756-2acbcf2141ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "newd = { t:expand(t) for t in get_teams(matchlist) }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "cf496f9c-226d-4d8e-b74b-2663d74820f9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'ALG': 'Algeria',\n",
       " 'ARG': 'Argentina',\n",
       " 'AUS': 'Australia',\n",
       " 'AUT': 'Austria',\n",
       " 'BEL': 'Belgium',\n",
       " 'BIH': 'Bosnia Herzegovina',\n",
       " 'BRA': 'Brazil',\n",
       " 'CAN': 'Canada',\n",
       " 'CIV': 'Ivory Coast',\n",
       " 'COD': 'Congo',\n",
       " 'COL': 'Colombia',\n",
       " 'CPV': 'Cape Verde',\n",
       " 'CRO': 'Croatia',\n",
       " 'CUW': 'Curacao',\n",
       " 'CZE': 'Czech Republic',\n",
       " 'ECU': 'Ecuador',\n",
       " 'EGY': 'Egypt',\n",
       " 'ENG': 'England',\n",
       " 'ESP': 'Spain',\n",
       " 'FRA': 'France',\n",
       " 'GER': 'Germany',\n",
       " 'GHA': 'Ghana',\n",
       " 'HAI': 'Haiti',\n",
       " 'IRN': 'Iran',\n",
       " 'IRQ': 'Iraq',\n",
       " 'JOR': 'Jordan',\n",
       " 'JPN': 'Japan',\n",
       " 'KOR': 'Korea',\n",
       " 'KSA': 'Saudi Arabia',\n",
       " 'MAR': 'Morocco',\n",
       " 'MEX': 'Mexico',\n",
       " 'NED': 'Netherlands',\n",
       " 'NOR': 'Norway',\n",
       " 'NZL': 'New Zealand',\n",
       " 'PAN': 'Panama',\n",
       " 'PAR': 'Paraguay',\n",
       " 'POR': 'Portugal',\n",
       " 'QAT': 'Qatar',\n",
       " 'RSA': 'South Africa',\n",
       " 'SCO': 'Scotland',\n",
       " 'SEN': 'Senegal',\n",
       " 'SUI': 'Switzerland',\n",
       " 'SWE': 'Sweden',\n",
       " 'TUN': 'Tunisia',\n",
       " 'TUR': 'Turkey',\n",
       " 'URU': 'Uruguay',\n",
       " 'USA': 'United States of America',\n",
       " 'UZB': 'Uzbekistan'}"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "newd"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8de1b8a7-f8f7-43f9-ad41-461099a7b94f",
   "metadata": {},
   "source": [
    "- Recall that `uniqd` created a list of unique items via keys of a dictionary\n",
    "- Here is a short way to do this using list comprehension"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "568af303-0723-4435-bf03-e40261a01666",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['RSA',\n",
       " 'CZE',\n",
       " 'BIH',\n",
       " 'PAR',\n",
       " 'SUI',\n",
       " 'MAR',\n",
       " 'SCO',\n",
       " 'TUR',\n",
       " 'CUW',\n",
       " 'JPN',\n",
       " 'ECU',\n",
       " 'TUN',\n",
       " 'CPV',\n",
       " 'EGY',\n",
       " 'URU',\n",
       " 'NZL',\n",
       " 'SEN',\n",
       " 'NOR',\n",
       " 'ALG',\n",
       " 'JOR',\n",
       " 'COD',\n",
       " 'CRO',\n",
       " 'PAN',\n",
       " 'COL',\n",
       " 'KOR',\n",
       " 'QAT',\n",
       " 'HAI',\n",
       " 'AUS',\n",
       " 'CIV',\n",
       " 'SWE',\n",
       " 'IRN',\n",
       " 'KSA',\n",
       " 'IRQ',\n",
       " 'AUT',\n",
       " 'UZB',\n",
       " 'GHA',\n",
       " 'MEX',\n",
       " 'CAN',\n",
       " 'BRA',\n",
       " 'USA',\n",
       " 'GER',\n",
       " 'NED',\n",
       " 'BEL',\n",
       " 'ESP',\n",
       " 'FRA',\n",
       " 'ARG',\n",
       " 'POR',\n",
       " 'ENG']"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list({ x[2]:1 for x in matchlist})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e695b662-59dc-40ca-9f62-dd7cf89ee394",
   "metadata": {},
   "source": [
    "- Uses the fact that a dictionary `d` when interpreted as a sequence is implcitly `d.keys()`\n",
    "- `list(d)` looks for a sequence `d`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abc0a457-b352-4ecc-8ee7-6f198d1812d9",
   "metadata": {},
   "source": [
    "- Can have multiple generators\n",
    "- Like nested loops, the left most generator is the outermost loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "7471a4a2-697b-4283-945c-c0af252951db",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(0, 0),\n",
       " (0, 1),\n",
       " (0, 2),\n",
       " (0, 3),\n",
       " (1, 0),\n",
       " (1, 1),\n",
       " (1, 2),\n",
       " (1, 3),\n",
       " (2, 0),\n",
       " (2, 1),\n",
       " (2, 2),\n",
       " (2, 3)]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (i,j) for i in range(3) for j in range(4) ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a68d22b-e72b-4446-85b7-aafcb19ab738",
   "metadata": {},
   "source": [
    "- **Example**: \"Small\" Pythagorean triples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "a467e79d-0a8b-4bc9-a647-daab169956ec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(3, 4, 5),\n",
       " (4, 3, 5),\n",
       " (5, 12, 13),\n",
       " (6, 8, 10),\n",
       " (8, 6, 10),\n",
       " (8, 15, 17),\n",
       " (9, 12, 15),\n",
       " (12, 5, 13),\n",
       " (12, 9, 15),\n",
       " (15, 8, 17)]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (x,y,z) for x in range(1,20) for y in range(1,20) for z in range(1,20) if x*x + y*y == z*z ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e16c208-990b-41b0-b2d4-4b0240872eea",
   "metadata": {},
   "source": [
    "- Avoid duplicates like `(3,4,5)`, `(4,3,5)` -- ensure that `y > x`\n",
    "- `y in range(x,20)` -- later generator can use value from an earlier one, like in a nested loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "8454d461-83a0-4857-9e4c-7f432e168e43",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (x,y,z) for x in range(1,20) for y in range(x,20) for z in range(x,20) if x*x + y*y == z*z ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30f76c96-a1f7-4394-b502-26644bafd163",
   "metadata": {},
   "source": [
    "- Can report the triples in a different order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "35f81e0f-6beb-499b-83ba-9eb816595c6a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(4, 3, 5), (12, 5, 13), (8, 6, 10), (15, 8, 17), (12, 9, 15)]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (y,x,z) for x in range(1,20) for y in range(x,20) for z in range(x,20) if x*x + y*y == z*z ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9a5d845",
   "metadata": {},
   "source": [
    "### Scope and global variables\n",
    "- The scope of a variable refers to the portion of the program where its value is available\n",
    "- If we refer to a value that is not defined in a function, it is looked up in the global context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "02be75d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def f():\n",
    "    y = x + 22\n",
    "    print(y)\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "14c15030-85f1-4514-bb64-36695d52d525",
   "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[29]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;66;03m# x = 7\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m f()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[28]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mf\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m f():\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     y = x + \u001b[32m22\u001b[39m\n\u001b[32m      3\u001b[39m     print(y)\n\u001b[32m      4\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[31mNameError\u001b[39m: name 'x' is not defined"
     ]
    }
   ],
   "source": [
    "# x = 7\n",
    "f()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "cd4c4ac9-eeba-4c15-8389-bfd97dc7991e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "29\n"
     ]
    }
   ],
   "source": [
    "x = 7\n",
    "f()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "009e036a",
   "metadata": {},
   "source": [
    "- As soon as we assign a variable a value inside a function, *all* instances of that variable are treated as local to the function\n",
    "- This decision is *static* based on the program text. In the code below, we cannot be sure that the assignment `x = 33` will execute, but Python still denotes `x` to be local to `f()`\n",
    "- Though the check is based on the static program text, the error is flagged only when the function executes. The definition of `f()` does not trigger an error though the problem is evident in the text of the function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "297f4b25",
   "metadata": {},
   "outputs": [],
   "source": [
    "def f():\n",
    "    y = x + 22\n",
    "    print(y)\n",
    "    if y > 1000:\n",
    "        x = 33\n",
    "    return\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "f1d4f69e-b6a2-4c30-b3c8-2cc338f69197",
   "metadata": {},
   "outputs": [
    {
     "ename": "UnboundLocalError",
     "evalue": "cannot access local variable 'x' where it is not associated with a value",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mUnboundLocalError\u001b[39m                         Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[32]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m      1\u001b[39m x = \u001b[32m7\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m f()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[31]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mf\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m f():\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     y = x + \u001b[32m22\u001b[39m\n\u001b[32m      3\u001b[39m     print(y)\n\u001b[32m      4\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m y > \u001b[32m1000\u001b[39m:\n\u001b[32m      5\u001b[39m         x = \u001b[32m33\u001b[39m\n",
      "\u001b[31mUnboundLocalError\u001b[39m: cannot access local variable 'x' where it is not associated with a value"
     ]
    }
   ],
   "source": [
    "x = 7\n",
    "f()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42ede9fd-381a-4ece-a68a-af16f5ce438f",
   "metadata": {},
   "source": [
    "- This static check applies even if it is impossible for the local assignment to be executed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "52df9392-f73a-47ab-87ec-5669bb6af3fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def checky():\n",
    "    y = x + 2\n",
    "    return\n",
    "    if False:\n",
    "        x = 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "4138cdc7-aa48-4f26-87d8-911b5ad6349a",
   "metadata": {},
   "outputs": [
    {
     "ename": "UnboundLocalError",
     "evalue": "cannot access local variable 'x' where it is not associated with a value",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mUnboundLocalError\u001b[39m                         Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[34]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m      1\u001b[39m x = \u001b[32m8\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m checky()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[33]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mchecky\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m checky():\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     y = x + \u001b[32m2\u001b[39m\n\u001b[32m      3\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[32m      4\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[32m      5\u001b[39m         x = \u001b[32m7\u001b[39m\n",
      "\u001b[31mUnboundLocalError\u001b[39m: cannot access local variable 'x' where it is not associated with a value"
     ]
    }
   ],
   "source": [
    "x = 8\n",
    "checky()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b7be1d2",
   "metadata": {},
   "source": [
    "- More examples of using global values within a function without redefining the variable "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "570ee35e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def display_count():\n",
    "    print(count)\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "670190c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def display_upto_count():\n",
    "    for i in range(count):\n",
    "        print(count+i)\n",
    "    return"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7c76b7d-a5bc-43fd-85ba-371d3650a939",
   "metadata": {},
   "source": [
    "- If we call `display_count()` without a global definition for `count` we get an error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "61b3ed37-648b-429d-a63e-6353aeaf739a",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'count' 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[37]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m display_count()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[35]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mdisplay_count\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m display_count():\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     print(count)\n\u001b[32m      3\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[31mNameError\u001b[39m: name 'count' is not defined"
     ]
    }
   ],
   "source": [
    "display_count()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4ef316b-2b46-412b-857a-a11e54d56fd7",
   "metadata": {},
   "source": [
    "- If `count` is available in the global context, the two functions work as expected"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "e3f0d201",
   "metadata": {},
   "outputs": [],
   "source": [
    "count = 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "746b1e0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "display_count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "8121a41a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n",
      "13\n"
     ]
    }
   ],
   "source": [
    "display_upto_count()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5fb13a0",
   "metadata": {},
   "source": [
    "- If we try to update `count` inside the function, both occurrences become local\n",
    "- The occurrence on the right hand side of the assignment generates an error because its value is now undefined\n",
    "- Once again, this *static* error is only triggered at run-time when the function executes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "1523eab6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def increment_local(k):\n",
    "    count = count+k\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "2ab211d9",
   "metadata": {},
   "outputs": [
    {
     "ename": "UnboundLocalError",
     "evalue": "cannot access local variable 'count' where it is not associated with a value",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mUnboundLocalError\u001b[39m                         Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[42]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m increment_local(\u001b[32m2\u001b[39m)\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[41]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mincrement_local\u001b[39m\u001b[34m(k)\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m increment_local(k):\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     count = count+k\n\u001b[32m      3\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[31mUnboundLocalError\u001b[39m: cannot access local variable 'count' where it is not associated with a value"
     ]
    }
   ],
   "source": [
    "increment_local(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "862d2351",
   "metadata": {},
   "source": [
    "- Reassigning a variable within a function disconnects it from the external variable with the same name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "232ca581",
   "metadata": {},
   "outputs": [],
   "source": [
    "def reset_local(k):\n",
    "    count = k\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "6200fc0e",
   "metadata": {},
   "outputs": [],
   "source": [
    "reset_local(77)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "e595dd1d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "count"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca7a5faa",
   "metadata": {},
   "source": [
    "- We can declare a variable to be `global` to override Python's default scope rules\n",
    "- `global` tells Python to treat the variable inside the function as one from the global context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "83036984",
   "metadata": {},
   "outputs": [],
   "source": [
    "def increment_global(k):\n",
    "    global count\n",
    "    count = count+k\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "98ed11e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "increment_global(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "3e952ab2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n"
     ]
    }
   ],
   "source": [
    "display_count()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9300f2a",
   "metadata": {},
   "source": [
    "- The default rule about local scope applies to mutable values as well"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "5ddd419b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def concat_local():\n",
    "    l1 = l1 + l2\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "cd804009",
   "metadata": {},
   "outputs": [
    {
     "ename": "UnboundLocalError",
     "evalue": "cannot access local variable 'l1' where it is not associated with a value",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mUnboundLocalError\u001b[39m                         Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[50]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m      1\u001b[39m l1 = [\u001b[32m1\u001b[39m,\u001b[32m2\u001b[39m,\u001b[32m3\u001b[39m]\n\u001b[32m      2\u001b[39m l2 = [\u001b[32m4\u001b[39m,\u001b[32m5\u001b[39m,\u001b[32m6\u001b[39m]\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m concat_local()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[49]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mconcat_local\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m concat_local():\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     l1 = l1 + l2\n\u001b[32m      3\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[31mUnboundLocalError\u001b[39m: cannot access local variable 'l1' where it is not associated with a value"
     ]
    }
   ],
   "source": [
    "l1 = [1,2,3]\n",
    "l2 = [4,5,6]\n",
    "concat_local()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "8e2ce199",
   "metadata": {},
   "outputs": [],
   "source": [
    "def concat_global():\n",
    "    global l1\n",
    "    l1 = l1 + l2\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "5f839b8e",
   "metadata": {},
   "outputs": [],
   "source": [
    "l1 = [1,2,3]\n",
    "l2 = [4,5,6]\n",
    "concat_global()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "6209c49d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([1, 2, 3, 4, 5, 6], [4, 5, 6])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1, l2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "872daf81",
   "metadata": {},
   "source": [
    "- We can define a value inside a function and \"export\" it outside by declaring it `global`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "c48cc401",
   "metadata": {},
   "outputs": [],
   "source": [
    "del(l1)\n",
    "del(l2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "427e0f30-f222-4619-a966-fa9aa443072f",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'l1' 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[55]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m l1\n",
      "\u001b[31mNameError\u001b[39m: name 'l1' is not defined"
     ]
    }
   ],
   "source": [
    "l1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "efe60af1-5696-45c8-bb9a-4f5f50415223",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'l2' 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[56]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m l2\n",
      "\u001b[31mNameError\u001b[39m: name 'l2' is not defined"
     ]
    }
   ],
   "source": [
    "l2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "dace6789",
   "metadata": {},
   "outputs": [],
   "source": [
    "def concat_global():\n",
    "    global l1\n",
    "    l1 = [1,2,3]\n",
    "    l1 = l1 + l2\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "41cacace",
   "metadata": {},
   "outputs": [],
   "source": [
    "l2 = [4,5,6]\n",
    "concat_global()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "875e3b0a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4, 5, 6]"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2aa568d8-8825-4627-9c39-9b49db81793d",
   "metadata": {},
   "source": [
    "- The following would work with *dynamic* scoping -- based on execution of program\n",
    "    - `init()` defines `b` and then calls `seta()`, so with dynamic scoping, `b` is known to `seta()`\n",
    "- Python uses *static* scoping -- based on text of program -- so this code generates an error\n",
    "- Most languages use static scoping because dynamic scoping makes it hard to reason about correctness"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "a5cdc366-db8c-41ea-9622-488b2a2348fc",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'b' 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[60]\u001b[39m\u001b[32m, line 9\u001b[39m\n\u001b[32m      5\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m init():\n\u001b[32m      6\u001b[39m     b = \u001b[32m7\u001b[39m\n\u001b[32m      7\u001b[39m     seta()\n\u001b[32m      8\u001b[39m \n\u001b[32m----> \u001b[39m\u001b[32m9\u001b[39m init()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[60]\u001b[39m\u001b[32m, line 7\u001b[39m, in \u001b[36minit\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      5\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m init():\n\u001b[32m      6\u001b[39m     b = \u001b[32m7\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m7\u001b[39m     seta()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[60]\u001b[39m\u001b[32m, line 2\u001b[39m, in \u001b[36mseta\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m seta():\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m     a = b + \u001b[32m5\u001b[39m\n\u001b[32m      3\u001b[39m     print(a)\n",
      "\u001b[31mNameError\u001b[39m: name 'b' is not defined"
     ]
    }
   ],
   "source": [
    "def seta():\n",
    "    a = b + 5\n",
    "    print(a)\n",
    "\n",
    "def init():\n",
    "    b = 7\n",
    "    seta()\n",
    "\n",
    "init()"
   ]
  }
 ],
 "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
}
