{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "12b02b53",
   "metadata": {},
   "source": [
    "<h2>Lists, Tuples and Loops</h2>\n",
    "<hr>\n",
    "<h3>Lists</h3>\n",
    "<br>Lists are a great tool for organising all kind of info. In contrast to most other languages one can mix types\n",
    "<h4>Initialise and index</h4>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "c913485b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L1: [1, 5, 'five', [1, 2, 3], 0]\n",
      "L2: ['Hey', 4.2, False, [1, 5, 'five', [1, 2, 3], 0]]\n",
      "The second letter of the third object in the fourth object in L2: i\n",
      "The object 1 step back from the end in L2: False\n",
      "Element 1 to 3(not included) [4.2, False, [1, 5, 'five', [1, 2, 3], 0]]\n",
      "All elements jumping 2 steps [1, 'five', 0]\n"
     ]
    }
   ],
   "source": [
    "#Basic lists\n",
    "l1 = [1,5,\"five\",[1,2,3],True]\n",
    "l2 = [\"Hey\",4.2,False,l1]\n",
    "\n",
    "#Changing content (list are mutable objects)\n",
    "l1[4] = 0\n",
    "print(f\"L1: {l1}\")\n",
    "print(f\"L2: {l2}\")\n",
    "#Digging deep\n",
    "print(f\"The second letter of the third object in the fourth object in L2: {l2[3][2][1]}\")\n",
    "#Negative index\n",
    "print(f\"The object 1 step back from the end in L2: {l2[-2]}\")\n",
    "\n",
    "#Getting pieces of a list(slicing) - works the same as with strings, just give the range we want [start:stop].\n",
    "#Note that object at \"start\" is included, but not the object at \"stop\"\n",
    "print(f\"Element 1 to 3(not included) {l2[1:3]}\")\n",
    "#Picking with a stride using [startindex:stop-place:stride]\n",
    "print(f\"All elements jumping 2 steps {l1[::2]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fa8e0d6",
   "metadata": {},
   "source": [
    "<h4>List methods</h4>\n",
    "<img src=\"image.png\" width=70%>\n",
    "<br>\n",
    "Lets try som of these"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "12162899",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Apples: 2\n",
      "Tangerines: 0\n",
      "Next banana, counting from pos: 3\n",
      "Reversed fruits: ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']\n",
      "Longer list: ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']\n",
      "Original list now sorted: ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']\n",
      "Popped fruit: pear\n",
      "The list after popping: ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange']\n"
     ]
    }
   ],
   "source": [
    "fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']\n",
    "#How many of the fruits\n",
    "print(f\"Apples: {fruits.count('apple')}\")\n",
    "print(f\"Tangerines: {fruits.count('tangerine')}\")\n",
    "#Finding position for the first banana\n",
    "pos = fruits.index('banana')\n",
    "#Find next banana starting at that position\n",
    "print(f\"Next banana, counting from pos: {fruits.index('banana', pos)}\")  \n",
    "\n",
    "fruits.reverse()\n",
    "print(f\"Reversed fruits: {fruits}\")\n",
    "\n",
    "#Add element\n",
    "fruits.append('grape')\n",
    "print(f\"Longer list: {fruits}\")\n",
    "\n",
    "#This will sort list in place\n",
    "fruits.sort()\n",
    "print(f\"Original list now sorted: {fruits}\")\n",
    "#Lifting out the last element actually removing it and returning it as output\n",
    "print(f\"Popped fruit: {fruits.pop()}\")\n",
    "print(f\"The list after popping: {fruits}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08575031",
   "metadata": {},
   "source": [
    "<h4>Tuples - Immutable lists</h4>\n",
    "There is a special kind of \"list\". It's caled <b>Tuple</b><br>\n",
    "Lets try this.."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "07b46975",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "New list: ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))\n",
      "Our tuple v: ([1, 2, 3], [3, 2, 1])\n",
      "Our tuple new: ([10, 2, 3], [3, 2, 1])\n",
      "v now as a list: [[10, 2, 3], [3, 2, 1]]\n",
      "a = 2, b = 1\n"
     ]
    }
   ],
   "source": [
    "#Basic tuple\n",
    "t = 12345, 54321, 'hello!'\n",
    "#Getting an element, exactly as with lists\n",
    "t[0]\n",
    "\n",
    "# Tuples may be nested:\n",
    "u = t, (1, 2, 3, 4, 5)\n",
    "print(f\"New list: {u}\")\n",
    "\n",
    "# Tuples are immutable:\n",
    "#t[0] = 88888, wont work\n",
    "\n",
    "# but they can contain mutable objects:\n",
    "v = ([1, 2, 3], [3, 2, 1])\n",
    "print(f\"Our tuple v: {v}\")\n",
    "new = v\n",
    "new[0][0] = 10\n",
    "print(f\"Our tuple new: {new}\")\n",
    "#One can transform a Tuple into a list quite easily\n",
    "myList = list(v)\n",
    "print(f\"v now as a list: {myList}\")\n",
    "\n",
    "#Clever use of tuples, swapping places/values.\n",
    "a = 1\n",
    "b = 2\n",
    "b,a = a,b\n",
    "print(f\"a = {a}, b = {b}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cb130fc",
   "metadata": {},
   "source": [
    "<h4>Loops</h4>\n",
    "<p>We need to repeat things quite often. There are 2 main types of loops</p>\n",
    "<ul>\n",
    "<li>While\n",
    "<li>For\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "63db02ef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lap nr: 0\n",
      "Lap nr: 1\n",
      "Lap nr: 2\n",
      "Lap nr: 3\n",
      "Lap nr: 4\n",
      "End of while-loop\n"
     ]
    }
   ],
   "source": [
    "#Basic while loop\n",
    "i = 0\n",
    "while i < 5:\n",
    "    print(f\"Lap nr: {i}\")\n",
    "    i += 1\n",
    "else:\n",
    "    print(\"End of while-loop\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f644ba17",
   "metadata": {},
   "source": [
    "<p>Sometimes we need to check user input and give the user a chance to give som decent input</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "297b1036",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Yiihaaa\n",
      "Yiihaaa\n",
      "Yiihaaa\n"
     ]
    }
   ],
   "source": [
    "def main():\n",
    "    number = get_number()\n",
    "    scream(number)\n",
    "\n",
    "#Getting input, handling the fact that you can get bad input\n",
    "def get_number():\n",
    "    while True:\n",
    "        n = int(input(\"How many times shall I scream? \"))\n",
    "        if n > 0:\n",
    "            break\n",
    "    return n\n",
    "\n",
    "\n",
    "def scream(n):\n",
    "    for _ in range(n):\n",
    "        print(\"Yiihaaa\")\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "83a038a1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lap nr: 0\n",
      "Lap nr: 1\n",
      "Lap nr: 2\n",
      "Lap nr: 3\n",
      "Lap nr: 4\n",
      "Skipping Lap nr: 1\n",
      "Skipping Lap nr: 3\n",
      "Skipping Lap nr: 5\n",
      "Skipping Lap nr: 7\n",
      "Skipping Lap nr: 9\n",
      "This will be repated \n",
      "This will be repated \n",
      "This will be repated \n",
      "This will be repated \n",
      "This will be repated \n",
      "\n"
     ]
    }
   ],
   "source": [
    "#Basic for-loop\n",
    "for i in range(5):\n",
    "    print(f\"Lap nr: {i}\")\n",
    "#With limits and stride\n",
    "for i in range(1,10,2):\n",
    "    print(f\"Skipping Lap nr: {i}\")\n",
    "\n",
    "#Fun fact with print...\n",
    "print(\"This will be repated \\n\"*5)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efadec28",
   "metadata": {},
   "source": [
    "<p>A really nice thing with for-loops and lists are that we can loop through lists. The fact is that when we use range we create a kind of a tuple on the fly to loop through.</p>\n",
    "Lets try this"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "78ddaa07",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cat 3\n",
      "window 6\n",
      "defenestrate 12\n"
     ]
    }
   ],
   "source": [
    "# Measure some strings:\n",
    "words = ['cat', 'window', 'defenestrate']\n",
    "for w in words:\n",
    "    print(w, len(w))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9397df8d",
   "metadata": {},
   "source": [
    "Lets try something a bit more mathematical, Fibonacci ;)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "a8173100",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578]\n"
     ]
    }
   ],
   "source": [
    "# Calculates and stores the first n Fibonacci numbers\n",
    "n = int(input(\"How high? \"))\n",
    "#The first 2\n",
    "fib = [2, 3]\n",
    "#Crunching through the algorithm creating a list\n",
    "for i in range(2, n+1):\n",
    "    fib.append(fib[i-1] + fib[i-2])\n",
    "print(fib)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "e79bcdc8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181  6765  10946  17711  28657  46368  75025  121393  196418  317811  514229  832040  1346269"
     ]
    }
   ],
   "source": [
    "# Calculates the first n Fibonacci numbers without storing\n",
    "n = int(input(\"How high? \"))\n",
    "# Keep track of the two most recent Fibonacci numbers\n",
    "a, b = 1, 1\n",
    "print(a, b, end='')\n",
    "for i in range(2, n+1):\n",
    "    # The next number (b) is a+b, and a becomes the previous b, using tuple swap\n",
    "    a, b = b, a+b\n",
    "    print(' ', b, end='')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56794cf4",
   "metadata": {},
   "source": [
    "<h4><code>break</code> and <code>continue</code> in loops</h4>\n",
    "<p>This is really useful</p>\n",
    "<ul>\n",
    "<li><code>break</code> escapes the current loop/if and continues the code after the block\n",
    "<li><code>continue</code> escapes the current lap in a loop and continues the loop with the next lap."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "76ef14d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "2\n",
      "4\n",
      "6\n",
      "8\n",
      "10\n",
      "12\n"
     ]
    }
   ],
   "source": [
    "#Simple example\n",
    "\n",
    "for x in range(20):\n",
    "    if x%2:\n",
    "        continue\n",
    "    if x == 14:\n",
    "        break\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a88fa42e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 is a prime number\n",
      "3 is a prime number\n",
      "4 equals 2 * 2\n",
      "5 is a prime number\n",
      "6 equals 2 * 3\n",
      "7 is a prime number\n",
      "8 equals 2 * 4\n",
      "9 equals 3 * 3\n"
     ]
    }
   ],
   "source": [
    "#A bit more to chew on, factor integers...\n",
    "for n in range(2, 10):\n",
    "    for x in range(2, n):\n",
    "        if n % x == 0:\n",
    "            print(n, 'equals', x, '*', n//x)\n",
    "            break\n",
    "    else:\n",
    "        # loop fell through without finding a factor\n",
    "        # Note that else in this case happens if the loop has not used break\n",
    "        print(n, 'is a prime number')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c252e978",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found an even number 2\n",
      "Found an odd number 3\n",
      "Found an even number 4\n",
      "Found an odd number 5\n",
      "Found an even number 6\n",
      "Found an odd number 7\n",
      "Found an even number 8\n",
      "Found an odd number 9\n"
     ]
    }
   ],
   "source": [
    "#Using continue\n",
    "for num in range(2, 10):\n",
    "    if num % 2 == 0:\n",
    "        print(\"Found an even number\", num)\n",
    "        continue\n",
    "    print(\"Found an odd number\", num)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6136e1a9",
   "metadata": {},
   "source": [
    "<p>Using <code>enumerate</code> to keep track of which element we use in a list</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "a56b24a9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]\n",
      "[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]\n"
     ]
    }
   ],
   "source": [
    "seasons = ['Spring', 'Summer', 'Fall', 'Winter']\n",
    "start0 = list(enumerate(seasons))\n",
    "start1 = list(enumerate(seasons, start=1))\n",
    "print(start0)\n",
    "print(start1)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7af12e4f",
   "metadata": {},
   "source": [
    "<h4>Dictionaries</h4>\n",
    "<p>This is a type of list where all items is in the for <code>key:value</code></p>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "d5335a35",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The dict: {'jack': 4098, 'sape': 4139, 'guido': 4127}\n",
      "The value for the key jack: 4098\n",
      "The dict again: {'jack': 1111, 'guido': 4127, 'irv': 4127}\n",
      "New list: ['jack', 'guido', 'irv']\n",
      "The original dict: {'jack': 1111, 'guido': 4127, 'irv': 4127}\n"
     ]
    }
   ],
   "source": [
    "#Simple dictionary\n",
    "tel = {'jack': 4098, 'sape': 4139}\n",
    "#Adding an item with a new key\n",
    "tel['guido'] = 4127\n",
    "print(f\"The dict: {tel}\")\n",
    "\n",
    "print(f\"The value for the key jack: {tel['jack']}\")\n",
    "\n",
    "#Erasing the object with key \"sape\"\n",
    "del tel['sape']\n",
    "#Adding a new post\n",
    "tel['irv'] = 4127\n",
    "#Changing existing post jack\n",
    "tel['jack'] = 1111\n",
    "print(f\"The dict again: {tel}\")\n",
    "\n",
    "#Converting the dict into a list, this will create a list with the keys from the dictionaries\n",
    "newList = list(tel)\n",
    "print(f\"New list: {newList}\")\n",
    "print(f\"The original dict: {tel}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56c3dfa3",
   "metadata": {},
   "source": [
    "One can use the <code>dict()</code> constructor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "a26e63cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'sape': 4139, 'guido': 4127, 'jack': 4098}\n"
     ]
    }
   ],
   "source": [
    "newDict = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])\n",
    "print(newDict)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2e97ad3",
   "metadata": {},
   "source": [
    "Lets try to loop through a dict..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c23033b7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gallahad the pure\n",
      "robin the brave\n"
     ]
    }
   ],
   "source": [
    "#Looping in a dict\n",
    "knights = {'gallahad': 'the pure', 'robin': 'the brave'}\n",
    "for k, v in knights.items():\n",
    "    print(k, v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa811cfb",
   "metadata": {},
   "source": [
    "<h4><code>zip</code></h4>\n",
    "<p>A bit more advanced but useful : <code>zip</code>.<br>Lets try </p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "3b993368",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'zip' object is not subscriptable",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m/Users/randlerm2/Documents/UU och Campus/Undervisning UU/Kurser 23-24/23 Coding in Python /Lectures/L4/4 - Lists,Tuples,Loops.ipynb Cell 30\u001b[0m line \u001b[0;36m6\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/randlerm2/Documents/UU%20och%20Campus/Undervisning%20UU/Kurser%2023-24/23%20Coding%20in%20Python%20/Lectures/L4/4%20-%20Lists%2CTuples%2CLoops.ipynb#X42sZmlsZQ%3D%3D?line=3'>4</a>\u001b[0m \u001b[39m#Creates an iterator\u001b[39;00m\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/randlerm2/Documents/UU%20och%20Campus/Undervisning%20UU/Kurser%2023-24/23%20Coding%20in%20Python%20/Lectures/L4/4%20-%20Lists%2CTuples%2CLoops.ipynb#X42sZmlsZQ%3D%3D?line=4'>5</a>\u001b[0m zipped \u001b[39m=\u001b[39m \u001b[39mzip\u001b[39m(questions, answers)\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/randlerm2/Documents/UU%20och%20Campus/Undervisning%20UU/Kurser%2023-24/23%20Coding%20in%20Python%20/Lectures/L4/4%20-%20Lists%2CTuples%2CLoops.ipynb#X42sZmlsZQ%3D%3D?line=5'>6</a>\u001b[0m \u001b[39mprint\u001b[39m(zipped[\u001b[39m0\u001b[39m])\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/randlerm2/Documents/UU%20och%20Campus/Undervisning%20UU/Kurser%2023-24/23%20Coding%20in%20Python%20/Lectures/L4/4%20-%20Lists%2CTuples%2CLoops.ipynb#X42sZmlsZQ%3D%3D?line=6'>7</a>\u001b[0m \u001b[39mfor\u001b[39;00m q, a \u001b[39min\u001b[39;00m zipped:\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/randlerm2/Documents/UU%20och%20Campus/Undervisning%20UU/Kurser%2023-24/23%20Coding%20in%20Python%20/Lectures/L4/4%20-%20Lists%2CTuples%2CLoops.ipynb#X42sZmlsZQ%3D%3D?line=7'>8</a>\u001b[0m     \u001b[39mprint\u001b[39m(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mWhat is your \u001b[39m\u001b[39m{\u001b[39;00mq\u001b[39m}\u001b[39;00m\u001b[39m?  It is \u001b[39m\u001b[39m{\u001b[39;00ma\u001b[39m}\u001b[39;00m\u001b[39m.\u001b[39m\u001b[39m\"\u001b[39m)\n",
      "\u001b[0;31mTypeError\u001b[0m: 'zip' object is not subscriptable"
     ]
    }
   ],
   "source": [
    "#Using zip on two equally long lists to \"pair\" them.\n",
    "questions = ['name', 'quest', 'favorite color']\n",
    "answers = ['lancelot', 'the holy grail', 'blue']\n",
    "#Creates an iterator\n",
    "zipped = zip(questions, answers)\n",
    "for q, a in zipped:\n",
    "    print(f\"What is your {q}?  It is {a}.\")\n",
    "\n",
    "#Converts the iterator into a list of tuples\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can convert an iterator to a list..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]\n"
     ]
    }
   ],
   "source": [
    "numbers = [1, 2, 3, 4]\n",
    "names = [\"one\", \"two\", \"three\", \"four\"]\n",
    "\n",
    "# Use the zip function to create an iterator of tuples\n",
    "zipped = zip(numbers, names)\n",
    "\n",
    "# Convert the iterator to a list\n",
    "zipped_list = list(zipped)\n",
    "\n",
    "# Print the new list\n",
    "print(zipped_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But an iterator can only be used once...\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]\n",
      "[]\n"
     ]
    }
   ],
   "source": [
    "numbers = [1, 2, 3, 4]\n",
    "names = [\"one\", \"two\", \"three\", \"four\"]\n",
    "\n",
    "zipped = zip(numbers, names)\n",
    "\n",
    "# Convert the iterator to a list, consuming it\n",
    "zipped_list = list(zipped)\n",
    "\n",
    "# At this point, zipped is exhausted. It has been \"used\".\n",
    "# If you try to convert it to a list again or iterate over it, it will be empty.\n",
    "another_list = list(zipped)  # This will be an empty list\n",
    "\n",
    "print(zipped_list)  # This will print the content of the zipped iterator\n",
    "print(another_list)  # This will print an empty list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Types and Copying in Python:\n",
    "\n",
    "### Immutable Types (copy acts like copy by value):\n",
    "- Examples include integers, floats, strings, and tuples.\n",
    "- When you copy an immutable object, you actually create a new object. However, for small integers and short strings, Python optimizes memory by reusing the same object.\n",
    "\n",
    "### Mutable Types (copy is copy by reference):\n",
    "- Examples include lists, dictionaries, and sets.\n",
    "- When you copy a mutable object, you are only copying the reference to the object, not the actual object. Changes made through any reference will reflect across all references.\n",
    "\n",
    "### Using copy\n",
    "\n",
    "In practical use, if you want to make a true copy of a mutable object in Python (like a list or a dictionary), you need to use methods like copy() for a shallow copy or deepcopy() from the copy module for a deep copy, which recursively creates new copies of nested objects."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <code>copy()</code>\n",
    "- Provided by the copy module.\n",
    "- Creates a shallow copy of an object.\n",
    "- For a shallow copy, a new object is created, and then references to the objects found in the original are inserted into it.\n",
    "- This means if you have a compound object (like a list of lists), the outer list is a new object but the inner lists are still references to the original lists.\n",
    "- Changes to mutable objects within the original will reflect in the shallow copy and vice versa."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[['X', 2, 3], [4, 5, 6]]\n"
     ]
    }
   ],
   "source": [
    "import copy\n",
    "original_list = [[1, 2, 3], [4, 5, 6]]\n",
    "shallow_copied_list = copy.copy(original_list)\n",
    "shallow_copied_list[0][0] = 'X'\n",
    "print(original_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### <code>deepcopy()</code>\n",
    "- Provided by the copy module.\n",
    "- Creates a deep copy of an object.\n",
    "- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.\n",
    "- Changes to any level of nested objects in the original will not affect the deep copy and vice versa.\n",
    "- More memory-intensive and slower in execution compared to copy(), but ensures complete independence of the copied object from the original."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1, 2, 3], [4, 5, 6]]\n"
     ]
    }
   ],
   "source": [
    "import copy\n",
    "original_list = [[1, 2, 3], [4, 5, 6]]\n",
    "deep_copied_list = copy.deepcopy(original_list)\n",
    "deep_copied_list[0][0] = 'X'\n",
    "print(original_list)  # Output: [[1, 2, 3], [4, 5, 6]]"
   ]
  }
 ],
 "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.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
