text: {
   "cells": [
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "tuple  # Tuples are another important data type, pervasive in Python without you even knowing it (at first)"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {
      "scrolled": true
     },
     "outputs": [],
     "source": [
      "1, 2, 3, 'a', 'b', 'c'  # You're using tuples just by putting commas in between a bunch of values"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "type((1, 2, 3, 'a', 'b', 'c'))  # YOu can confirm this fact, but when you do you HAVE TO use the normally optional parenthesis."
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "atuple = 1, 2, 3, 'a', 'b', 'c'  # The fact you usually don't need the parenthesis leads to extremely PYTHONIC coding style.\n",
      "atuple"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "atuple = (1, 2, 3, 'a', 'b', 'c')  # This is the same as doing this, a more official way to create a tuple.\n",
      "atuple"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "atuple = tuple((1, 2, 3, 'a', 'b', 'c'))  # There's even more formal ways to create a tuple. But why would you?\n",
      "atuple"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "alist = list((1, 2, 3, 'a', 'b', 'c'))  # You'll also learn about lists which use square brackets instead of parenthesis.\n",
      "alist"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "a, b, c = 1, 2, 3  # The comma trick usually used for tuples can ALSO be used to define multiple variables at once.\n",
      "print(a)\n",
      "print(b)\n",
      "print(c)"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "a = 'first', 'second', 'third'  # Using a single variable name with comma seperated values makes a tuple.\n",
      "a"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {
      "scrolled": false
     },
     "outputs": [],
     "source": [
      "for x in a:\n",
      "    print(x)\n",
      "\n",
      "[print(x) for x in a]  # You can do many of the same things with a tuple as with a list."
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "mutable = [0, 0, 0, 0]  # But lists are made to be very dynamic and use LOTS of computer resources for tricks like this.\n",
      "mutable[2] = 'foo'\n",
      "mutable"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "immutable = (0, 0, 0, 0)  # Tuples are an immutable data-type, meaning when they're set, they stay that way (error intentional)\n",
      "immutable[2] = 'foo'"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "list_of_tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]  # Tuples are particularly useful as the rows in row & column shapes.\n",
      "for a_tuple in list_of_tuples:\n",
      "    print(a_tuple)"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {
      "scrolled": true
     },
     "outputs": [],
     "source": [
      "a = 'first', 'second', 'third'\n",
      "print(a)\n",
      "print(*a)  # Using an asterisk before a tuple-name sort of de-tuples it."
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "def foo(*args):\n",
      "    for arg in args:  # This is useful when making functions that support arbitrary numbers of parameters.\n",
      "        print(arg)\n",
      "    \n",
      "foo('first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'and', 'so', 'on')  # But this gets ahead of ourselves."
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "def show(arg):\n",
      "    print(arg)  # We're normally taught first how functions usually take one input.\n",
      "\n",
      "show('me')"
     ]
    },
    {
     "cell_type": "code",
     "execution_count": null,
     "metadata": {},
     "outputs": [],
     "source": [
      "def show(arg1, arg2):\n",
      "    print(arg1, arg2)  # We're normally taught first how functions usually take one input.\n",
      "\n",
      "show('me', 'too')  # Without the asterisk, you'd have go code the function to expect eacy separate argument."
     ]
    }
   ],
   "metadata": {
    "kernelspec": {
     "display_name": "Python 3",
     "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.6.5"
    }
   },
   "nbformat": 4,
   "nbformat_minor": 2
  }
  