{
 "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
}
