{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1cfea0af",
   "metadata": {},
   "outputs": [],
   "source": [
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "# https://geekflare.com/python-unpacking-operators/\n",
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "\n",
    "\n",
    "# Intro: some concepts\n",
    "\n",
    "# Iterable: Any sequence that can be iterated by a for-loop, like:\n",
    "#     sets, lists, tuples, and dictionaries\n",
    "\n",
    "# Callable: A Python object that can be called using double parenthesis (), \n",
    "# for example, myfunction()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "a147f94b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 3)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# * can be unary or binary operator in Python:\n",
    "#     Binary:  3 * 4 (multiply)\n",
    "#     Unary:   *x    is an UNPACK operator for lists\n",
    "\n",
    "range(3)      # No unpacking"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "1010471f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 1, 2)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*range(3),    # ****** NOTICE the trailing COMMA !!! ******\n",
    "\n",
    "              # BECAUSE: starred assignment target must be in a list or tuple\n",
    "              # The COMMAN make it a TUPLE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "32108b4a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cables\n",
      "headphones\n",
      "USB\n"
     ]
    }
   ],
   "source": [
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "# What is \"unpacking\" ?\n",
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "\n",
    "\n",
    "# ***********************************\n",
    "# Unpack a list manually\n",
    "# ***********************************\n",
    "\n",
    "mybox = ['cables', 'headphones', 'USB']\n",
    "item1, item2, item3 = mybox\n",
    "print(item1)\n",
    "print(item2)\n",
    "print(item3)\n",
    "\n",
    "# Works if you have the EXACT number of items "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "65a00f44",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "not enough values to unpack (expected 3, got 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Input \u001b[0;32mIn [9]\u001b[0m, in \u001b[0;36m<cell line: 4>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;66;03m# FAILED unpack operation\u001b[39;00m\n\u001b[1;32m      3\u001b[0m mybox \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcables\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mheadphones\u001b[39m\u001b[38;5;124m'\u001b[39m]\n\u001b[0;32m----> 4\u001b[0m item1, item2, item3 \u001b[38;5;241m=\u001b[39m mybox\n",
      "\u001b[0;31mValueError\u001b[0m: not enough values to unpack (expected 3, got 2)"
     ]
    }
   ],
   "source": [
    "# FAILED unpack operation\n",
    "\n",
    "mybox = ['cables', 'headphones']\n",
    "item1, item2, item3 = mybox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "8d2c9ab8",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "too many values to unpack (expected 3)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Input \u001b[0;32mIn [10]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m mybox \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcables\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mheadphones\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mUSB\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmic\u001b[39m\u001b[38;5;124m'\u001b[39m]\n\u001b[0;32m----> 2\u001b[0m item1, item2, item3 \u001b[38;5;241m=\u001b[39m mybox\n",
      "\u001b[0;31mValueError\u001b[0m: too many values to unpack (expected 3)"
     ]
    }
   ],
   "source": [
    "mybox = ['cables', 'headphones', 'USB', 'mic']\n",
    "item1, item2, item3 = mybox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c8a6d5ab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "5\n",
      "[2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "# The * unpack operator:\n",
    "#\n",
    "#    The asterisk operator (*) is used to unpack all the values of an iterable \n",
    "#    that have not been assigned yet.\n",
    "\n",
    "l = [1, 2, 3, 4, 5]\n",
    "first, *unused, last = l      # Unpack into 3 portions: first, * , last\n",
    "\n",
    "print(first)\n",
    "print(last)\n",
    "print(unused)\n",
    "\n",
    "# Comment:\n",
    "#   The preferred way to discard values is to use an underscore variable (_)\n",
    "#\n",
    "# I.e.:   \n",
    "#         first, *_, last = l "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "6d2aca57",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "[]\n"
     ]
    }
   ],
   "source": [
    "# The * unpack operator works even if the list is empty\n",
    "\n",
    "first, *_, last = [1,2]\n",
    "\n",
    "print(first)\n",
    "print(last)\n",
    "print(_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "92e70804",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2]\n",
      "<class 'list'>\n"
     ]
    }
   ],
   "source": [
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "# Important note:\n",
    "#\n",
    "#      The LHS * variable must be a list or a tuple\n",
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "\n",
    "# This works:\n",
    "*x, = [1,2]           # The COMMA makes x a LIST variable\n",
    "print(x)\n",
    "print(type(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "fcec10a9",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "starred assignment target must be in a list or tuple (887693060.py, line 3)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Input \u001b[0;32mIn [24]\u001b[0;36m\u001b[0m\n\u001b[0;31m    *x = [1,2]\u001b[0m\n\u001b[0m    ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m starred assignment target must be in a list or tuple\n"
     ]
    }
   ],
   "source": [
    "# This FAILS:\n",
    "\n",
    "*x = [1,2]   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "93b1f196",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['H', 'e', 'l', 'l', 'o']\n",
      "<class 'list'>\n"
     ]
    }
   ],
   "source": [
    "# Unpack a string\n",
    "\n",
    "*s, = \"Hello\"\n",
    "print(s)\n",
    "print(type(s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "d09de96d",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (4276196861.py, line 8)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Input \u001b[0;32mIn [29]\u001b[0;36m\u001b[0m\n\u001b[0;31m    **greetings, = {'hello': 'HELLO', 'bye':'BYE'}\u001b[0m\n\u001b[0m    ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "# The ** operator unpacks a dictionary\n",
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "\n",
    "# We CANNOT unpack a dictionary to a single variable \n",
    "# (as we’ve been doing with tuples and lists):\n",
    "\n",
    "**greetings, = {'hello': 'HELLO', 'bye':'BYE'} "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "414af78c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'fish': 3, 'meat': 5, 'pasta': 9, 'red': 'intensity', 'yellow': 'happiness'}"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# One usage of ** is to merge 2 dictionaries into one by:\n",
    "#\n",
    "#    (1) unpack each dictionary\n",
    "#    (2) concatenate them\n",
    "\n",
    "dict1 = {'fish':3, 'meat':5, 'pasta':9} \n",
    "dict2 = {'red': 'intensity', 'yellow':'happiness'}\n",
    "\n",
    "merged = {**dict1, **dict2}\n",
    "merged"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "8bea0fc5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12\n",
      "12\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "\n",
    "\n",
    "# How to use * in functions\n",
    "\n",
    "# Problem:\n",
    "#\n",
    "#   Write a product function that multiply all its arguments\n",
    "\n",
    "# Naive function: can ONLY multiply 2 numbers\n",
    "def product(n1, n2):\n",
    "    return n1 * n2\n",
    "\n",
    "# We can all it with 2 parameters:\n",
    "print(product(3,4))\n",
    "\n",
    "# But ALSO with an UNPACKED list:\n",
    "print( product( *[3,4] ) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "c91d7922",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "product() takes 2 positional arguments but 3 were given",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[0;32mIn [39]\u001b[0m, in \u001b[0;36m<cell line: 4>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;66;03m# The NAIVE product function implementation does not handle \u001b[39;00m\n\u001b[1;32m      2\u001b[0m \u001b[38;5;66;03m# a list of arbitrary length:\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m \u001b[38;5;28mprint\u001b[39m( \u001b[43mproduct\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m,\u001b[49m\u001b[38;5;241;43m4\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m5\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[43m)\u001b[49m )\n",
      "\u001b[0;31mTypeError\u001b[0m: product() takes 2 positional arguments but 3 were given"
     ]
    }
   ],
   "source": [
    "# The NAIVE product function implementation does not handle \n",
    "# a list of arbitrary length:\n",
    "\n",
    "print( product( *[3,4, 5] ) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "30d03db8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'tuple'>\n",
      "(2, 3, 4)\n",
      "24\n",
      "\n",
      "<class 'tuple'>\n",
      "(2, 3, 4)\n",
      "24\n"
     ]
    }
   ],
   "source": [
    "# To handle list of arbitrary length, we RE-WRITE the product function:\n",
    "\n",
    "def product(*args):\n",
    "#           ^^^^^^ args is ALWAYS a TUPLE !!\n",
    "    print(type(args))\n",
    "    print(args)\n",
    "    result = 1\n",
    "    for i in args:\n",
    "            result *= i\n",
    "    return result\n",
    "\n",
    "print( product(2,3,4) )\n",
    "\n",
    "print()\n",
    "\n",
    "# Or:\n",
    "print( product( *[2,3,4]) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "7503a35f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'id': 12112, 'location': 'london', 'net_worth': 12000}\n",
      "Type(kwargs) =  <class 'dict'>\n",
      "Melissa: id = 12112, location = london, net_worth = 12000, \n",
      "<class 'str'>\n",
      "\n",
      "{'id': 12112, 'location': 'london', 'net_worth': 12000}\n",
      "Type(kwargs) =  <class 'dict'>\n",
      "Melissa: id = 12112, location = london, net_worth = 12000, \n",
      "<class 'str'>\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "\n",
    "\n",
    "# How to use ** to unpack dictionaries\n",
    "\n",
    "# The ** operator is used exclusively for dictionaries\n",
    "# With the ** operator we’re able to pass key-value pairs \n",
    "# to the function as a parameter.\n",
    "\n",
    "def make_person(name, **kwargs):\n",
    "    print(kwargs)\n",
    "    print(\"Type(kwargs) = \", type(kwargs))\n",
    "    result = name + ': '\n",
    "    \n",
    "    # Loop through the dictionary \"kwargs\"\n",
    "    for key, value in kwargs.items():\n",
    "        result += f'{key} = {value}, '      # This is an \"f-string\"\n",
    "    return result\n",
    "\n",
    "x = make_person('Melissa', id=12112, location='london', net_worth=12000)\n",
    "#                          ^^^^^^^^^ this is a keyword parameter !!!\n",
    "\n",
    "print(x)\n",
    "print(type(x))\n",
    "\n",
    "# *************************************************\n",
    "# This is what is really happening:\n",
    "# *************************************************\n",
    "print()\n",
    "d = {'id': 12112, 'location': 'london', 'net_worth': 12000}\n",
    "x = make_person('Melissa', **d)\n",
    "#                          ^^^^ **d unpacks dictionary are a series of individual args\n",
    "print(x)\n",
    "print(type(x))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "feca5a49",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type args:  <class 'tuple'>\n",
      "args:  ('Python', 'The', 'Best')\n",
      "Type kwargs:  <class 'dict'>\n",
      "kwargs:  {'language': 'Python', 'users': 'A lot'}\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "\n",
    "\n",
    "# What happens when we combine *args and **kwargs:\n",
    "\n",
    "def my_final_function(*args, **kwargs):\n",
    "    print('Type args: ', type(args))\n",
    "    print('args: ', args)\n",
    "    print('Type kwargs: ', type(kwargs))\n",
    "    print('kwargs: ', kwargs)\n",
    "    \n",
    "my_final_function('Python', 'The', 'Best', language='Python', users='A lot')\n",
    "#                 ^^^^^^^ Positional param ^^^^^^^^^^^^^^^^^ keyword parameter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "e1179352",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (3145274788.py, line 6)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Input \u001b[0;32mIn [64]\u001b[0;36m\u001b[0m\n\u001b[0;31m    my_final_function(language='Python', users='A lot', 'Python', 'The', 'Best')\u001b[0m\n\u001b[0m                                                        ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "# This does NOT work due to built-in limitation in Python:\n",
    "#\n",
    "#     Positional params MUST be specified before keyword params\n",
    "#\n",
    "\n",
    "my_final_function(language='Python', users='A lot', 'Python', 'The', 'Best')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "515be7ea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Summary:\n",
    "#\n",
    "#   Positional parameters ==> tuple\n",
    "#   Keyword parameters    ==> dictionary\n",
    "#\n",
    "# Parameter passing rule:\n",
    "#\n",
    "#   func( positional params, keyword pararms)\n",
    "#\n",
    "# *args are used to pass non-key-worded parameters to functions\n",
    "# **kwargs are used to pass keyworded parameters to functions.\n",
    "#\n",
    "# That's why:\n",
    "#\n",
    "#      func( *args, **kwargs )\n",
    "#\n",
    "# can handle VARIABLE length parameters in Python functions\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "35f37663",
   "metadata": {},
   "outputs": [],
   "source": [
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "# PEP 448  Additional Unpacking Generalizations\n",
    "#\n",
    "# https://peps.python.org/pep-0448/\n",
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "962dbf92",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'x': 1, 'y': 2, 'z': 3}"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Function calls are proposed to support an arbitrary number of unpackings \n",
    "# rather than just one:\n",
    "\n",
    "print(*[1], *[2], 3)\n",
    "dict(**{'x': 1}, y=2, **{'z': 3})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "c170f40b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4\n",
      "[0, 1, 2, 3, 4]\n",
      "{0, 1, 2, 3, 4}\n",
      "{'x': 1, 'y': 2}\n"
     ]
    }
   ],
   "source": [
    "# Unpacking is proposed to be allowed inside tuple, list, set, and dictionary displays:\n",
    "\n",
    "print(*range(4), 4)\n",
    "print([*range(4), 4])\n",
    "print({*range(4), 4})\n",
    "print({'x': 1, **{'y': 2}})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "b8e353ca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'x': 2}\n",
      "{'x': 1}\n"
     ]
    }
   ],
   "source": [
    "# In dictionaries, later values will always override earlier ones:\n",
    "\n",
    "print({'x': 1, **{'x': 2}})\n",
    "print({**{'x': 2}, 'x': 1})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "609a21c3",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "iterable unpacking cannot be used in comprehension (53009418.py, line 7)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Input \u001b[0;32mIn [84]\u001b[0;36m\u001b[0m\n\u001b[0;31m    {*item for item in ranges}\u001b[0m\n\u001b[0m     ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m iterable unpacking cannot be used in comprehension\n"
     ]
    }
   ],
   "source": [
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "# Some weird expressions\n",
    "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "ranges = [range(i) for i in range(3)]\n",
    "print(ranges)\n",
    "\n",
    "{*item for item in ranges}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96c1c685",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Passing Tuples and Dicts\n",
    "\n",
    "(1) Tuples can be expanded into variable arguments.\n",
    "\n",
    "numbers = (2,3,4)\n",
    "f(1, *numbers)      # Same as f(1,2,3,4)\n",
    "\n",
    "(2) Dictionaries can also be expanded into keyword arguments.\n",
    "\n",
    "options = {\n",
    "    'color' : 'red',\n",
    "    'delimiter' : ',',\n",
    "    'width' : 400\n",
    "}\n",
    "f(data, **options)\n",
    "# Same as f(data, color='red', delimiter=',', width=400)\n",
    "\n",
    "\n",
    "\"\"\""
   ]
  }
 ],
 "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.8.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
