{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "super-sweden",
   "metadata": {},
   "source": [
    "<!--\n",
    "title: Further Data Structures\n",
    "type: lesson\n",
    "duration: 00:40\n",
    "creator: Steve Peters\n",
    "-->\n",
    "\n",
    "## ![](https://s3.amazonaws.com/python-ga/images/GA_Cog_Medium_White_RGB.png)  {.separator}\n",
    "\n",
    "<h1>Python Programming: Sets and Tuples</h1>\n",
    "\n",
    "<!--\n",
    "\n",
    "## Overview\n",
    "This lesson focuses on sets and tuples. It starts with sets, encompassing  We Dos as new functions are introduced, then goes into tuples. It ends with the `type` function and a You Do. If there's time, after the \"Additional Reading\" slides, there is a sets exercise. This exercises are also in the `xx-additional-exercises` folder, if you don't get to it.\n",
    "\n",
    "## Important Notes or Prerequisites\n",
    "- The students will be asked to build upon their knowledge of the `list`, so a solid understanding of this concept will be vital.\n",
    "- The \"why\" of each datatype is essential to impart to students and your checks for understanding may keep circling back around to the \"why\".\n",
    "- Much of this lesson contrasts the three data types (tuples, sets, lists) to each other, so that students can see them side by side and start to internalize the differences.\n",
    "\n",
    "## Learning Objectives\n",
    "In this lesson, students will:\n",
    "\n",
    "- Perform common actions with sets.\n",
    "- Perform common actions with tuples.\n",
    "- Know when to use each of the different collection structures.\n",
    "\n",
    "\n",
    "## Duration\n",
    "40 minutes\n",
    "\n",
    "### Timing note:\n",
    "- If there's time remaining at the end, giving exercises involving multiple contrasting sets, tuples, and lists would be great.\n",
    "- There is, in the `xx-additional-exercises` folder in the parent folder, a set equals challenge that you should give in class if there's time, and if not, give as homework.\n",
    "\n",
    "## Suggested Agenda\n",
    "\n",
    "| Time | Activity |\n",
    "| --- | --- |\n",
    "| 0:00 - 0:02 | Welcome |\n",
    "| 0:02 - 0:20 | Sets |\n",
    "| 0:20 - 0:37 | Tuples |\n",
    "| 0:37 - 0:40  | Summary |\n",
    "\n",
    "## In Class: Materials\n",
    "- Projector\n",
    "- Internet connection\n",
    "- Python3\n",
    "-->\n",
    "\n",
    "---\n",
    "\n",
    "## Learning Objectives\n",
    "\n",
    "*After this lesson, you will be able to:*\n",
    "\n",
    "- Perform common actions with sets.\n",
    "- Perform common actions with tuples.\n",
    "- Know when to use different data structures.\n",
    "\n",
    "<aside class=\"notes\">\n",
    "\n",
    "**Teaching Tip**:\n",
    "\n",
    "- Quickly overview these; perhaps write them on the board.\n",
    "\n",
    "</aside>\n",
    "\n",
    "---\n",
    "\n",
    "## Discussion: Lists\n",
    "\n",
    "Here are some lists:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "beautiful-discipline",
   "metadata": {},
   "outputs": [],
   "source": [
    "unique_colors = [\"red\", \"yellow\", \"red\", \"green\", \"red\", \"yellow\"]\n",
    "subscribed_emails = [\"mary@gmail.com\", \"opal@gmail.com\", \"mary@gmail.com\", \"sayed@gmail.com\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "waiting-tokyo",
   "metadata": {},
   "source": [
    "\n",
    "What could be a problem here?\n",
    "\n",
    "---\n",
    "\n",
    "## Introducing Sets\n",
    "\n",
    "\n",
    "Lists:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "standing-stand",
   "metadata": {},
   "outputs": [],
   "source": [
    "unique_colors_list = [\"red\", \"yellow\", \"red\", \"green\", \"red\", \"yellow\"]\n",
    "subscribed_emails_list = [\"mary@gmail.com\", \"opal@gmail.com\", \"mary@gmail.com\", \"sayed@gmail.com\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "chicken-addiction",
   "metadata": {},
   "source": [
    "\n",
    "Sets: an unordered collection of unique elements. These are powerful because set theory operations can be applied to them in O(1) time.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ahead-puzzle",
   "metadata": {},
   "outputs": [],
   "source": [
    "unique_colors_set = {\"green\", \"yellow\", \"red\"}\n",
    "subscribed_emails_set = {\"mary@gmail.com\", \"opal@gmail.com\", \"sayed@gmail.com\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "copyrighted-underwear",
   "metadata": {},
   "source": [
    "\n",
    "- Notice the `{}` versus the `[]`.\n",
    "\n",
    "---\n",
    "\n",
    "\n",
    "## How Can We Make a Set?\n",
    "\n",
    "If we explicitly cast a set from a list, Python removes duplicates automatically.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "sharing-orlando",
   "metadata": {},
   "outputs": [],
   "source": [
    "my_set = set(a_list_to_convert)\n",
    "\n",
    "# In action:\n",
    "unique_colors_list = [\"red\", \"yellow\", \"red\", \"green\", \"red\", \"yellow\"]\n",
    "unique_colors_set = set(unique_colors_list)\n",
    "# => {\"green\", \"yellow\", \"red\"}\n",
    "\n",
    "# In action:\n",
    "unique_colors_set_2 = set([\"red\", \"yellow\", \"red\", \"green\", \"red\", \"yellow\"])\n",
    "# => {\"green\", \"yellow\", \"red\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "historical-impossible",
   "metadata": {},
   "source": [
    "\n",
    "We can make a set directly using curly braces:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "protective-easter",
   "metadata": {},
   "outputs": [],
   "source": [
    "colors = {\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"indigo\", \"violet\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "broke-clearance",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Important Note: Sets\n",
    "\n",
    "Lists are always in the same order:\n",
    "\n",
    "- `my_list = [\"green\", \"yellow\", \"red\"]` is always going to be`[\"green\", \"yellow\", \"red\"]`\n",
    "- `my_list[0]` is always  `\"green\"`; `my_list[1]` is always `\"yellow\"`; `my_list[2]` is always `\"red\"`.\n",
    "\n",
    "Sets are not like this! Similar to dictionaries, they're not ordered.\n",
    "\n",
    "- `my_set = {\"green\", \"yellow\", \"red\"}` could later be `{\"red\", \"yellow\", \"green\"}`!\n",
    "- Note that python defaults to displaying an ascending sort of a set. Although this is displayed to the user when the variable is called via the interpreter, _the order cannot be relied upon_.\n",
    "\n",
    "We **cannot** do:  `my_set[0]` - sets are unordered, and a `TypeError`\n",
    "exception will be thrown.\n",
    "\n",
    "---\n",
    "\n",
    "## We Do: Creating a Set from a List\n",
    "\n",
    "Let's make some sets!\n",
    "\n",
    "- Make a list `clothing_list` containing the main color of your classmates' clothing.\n",
    "- Using `clothing_list`, make a set named `clothing_set`.\n",
    "- Use a `for` loop to print out both `clothing_list` and `clothing_set`.\n",
    "- Try to print an index!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "conditional-brake",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "italic-drinking",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## We Do: Adding to a Set\n",
    "\n",
    "How do we add more to a set?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "confidential-documentary",
   "metadata": {},
   "outputs": [],
   "source": [
    "# In a list:\n",
    "clothing_list.append(\"red\")\n",
    "\n",
    "# In a set\n",
    "clothing_set.add(\"red\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "postal-vinyl",
   "metadata": {},
   "source": [
    "\n",
    "`add` vs `append` - this is because we can't guarantee it's going at the end!\n",
    "\n",
    "Let's add a few colors to `clothing_list` and `clothing_set` and then print them.\n",
    "\n",
    "- What happens if you add a duplicate?\n",
    "\n",
    "---\n",
    "\n",
    "## We Do: Removing from a List and a Set\n",
    "\n",
    "Remember, lists are always the same order and sets are not!\n",
    "\n",
    "- With the set `{\"green\", \"yellow\", \"red\"}`, `my_set[0]` could be `green`, `red`, or `yellow`.\n",
    "\n",
    "So thus, we need to be careful about removal:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "clear-rwanda",
   "metadata": {},
   "outputs": [],
   "source": [
    "# In a list:\n",
    "clothing_list.pop() # Removes and returns the last item in the list.\n",
    "clothing_list.pop(0) # Removes and returns a specific (here, the first) item in the list.\n",
    "\n",
    "# In a set\n",
    "clothing_set.pop() # Removes and returns an arbitrary element. This is probably not what you want to do in most cases.\n",
    "# clothing_set.pop(0) # Python throws a TypeError error (pop takes no arguments)\n",
    "clothing_set.remove('red') # This removes an element from the set directly, and raises KeyError if the element is not present. This is the most common use.\n",
    "clothing_set.discard('red') # This removes an element from the set directly, but does NOT throw a KeyError if the element is not present in the set."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cheap-killer",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## We Do: Set Intersection\n",
    "\n",
    "- One thing that sets are _really_ good at is _relational algebra_ (set theory). This is a fancy word for a SQL join, or comparing elements between two sets.\n",
    "- Sets are really good at this because they use the same [hashing trick](https://en.wikipedia.org/wiki/Hash_table) under the hood that dictionaries use and makes them so fast.\n",
    "\n",
    "Let's start by making two sets:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reverse-demonstration",
   "metadata": {},
   "outputs": [],
   "source": [
    "set1 = {1, 2, 3, 4, 5}\n",
    "set2 = {4, 5, 6, 7, 8}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "owned-noise",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## We Do: Set Intersection\n",
    "\n",
    "\n",
    "Now let's use the `.intersection()` set method to find out _what elements these two sets have in common_:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "opened-connectivity",
   "metadata": {},
   "outputs": [],
   "source": [
    "set1.intersection(set2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "persistent-jacob",
   "metadata": {},
   "source": [
    "\n",
    "Yields the result: `{4, 5}`\n",
    "\n",
    "- This makes sense, the two sets share the elements `4` and `5`.\n",
    "- Note that this is commutative, meaning we could also write `set2.intersection(set1)` and receive the same result.\n",
    "\n",
    "---\n",
    "\n",
    "## We Do: Set Differences\n",
    "\n",
    "- Instead of finding _elements in common_ between two sets, we can also find _their differences_.\n",
    "- To do this, we use `.difference()`.\n",
    "- Note that this method _is not commutative_, meaning _order matters_.\n",
    "- The difference is what is contained in the _first_ set, _but not in the second set_.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "neural-reform",
   "metadata": {},
   "outputs": [],
   "source": [
    "set1.difference(set2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "equal-prince",
   "metadata": {},
   "source": [
    "\n",
    "Yields the result: `{1, 2, 3}`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "breeding-vector",
   "metadata": {},
   "outputs": [],
   "source": [
    "set2.difference(set1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "photographic-channels",
   "metadata": {},
   "source": [
    "Yields the result: `{6, 7, 8}`\n",
    "\n",
    "---\n",
    "\n",
    "## Quick Review: Sets vs. Lists\n",
    "\n",
    "**Lists**:\n",
    "\n",
    "- The original, normal object.\n",
    "- Created with `[]`.\n",
    "- `append()`, `insert(index)`, `pop()`, `pop(index)`.\n",
    "- Duplicates and mutable.\n",
    "\n",
    "**Sets**:\n",
    "\n",
    "- Lists without duplicates.\n",
    "- Created with `{}` or with `set(my_list)`.\n",
    "- `add()` and `remove(element)`.\n",
    "\n",
    "---\n",
    "## Quick Review: Sets vs. Lists"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "exclusive-safety",
   "metadata": {},
   "outputs": [],
   "source": [
    "### Creation ###\n",
    "# List\n",
    "my_list = [\"red\",  \"yellow\", \"green\", \"red\"]\n",
    "# Sets\n",
    "my_set = {\"red\",  \"yellow\", \"green\"}\n",
    "my_set2 = set(my_list)\n",
    "my_set = set(a_list_to_convert)\n",
    "\n",
    "### Appending a New Value ###\n",
    "my_list.append(\"blue\")\n",
    "my_set.add(\"blue\")\n",
    "\n",
    "### Appending a Duplicate ###\n",
    "my_list.append(\"blue\")\n",
    "# => my_list = [\"red\",  \"yellow\", \"green\", \"red\", \"blue\",  \"blue\"]\n",
    "my_set.add(\"blue\")\n",
    "# => my_set = {\"red\",  \"yellow\", \"green\", \"blue\"}\n",
    "\n",
    "### Removing items: ###\n",
    "my_list.pop(1)\n",
    "my_set.remove(\"red\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "golden-crest",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Discussion: Immutability Thoughts\n",
    "\n",
    "A set is a type of list which doesn't allow duplicates.\n",
    "\n",
    "What if, instead, we have a list we don't want to change?\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "hourly-asbestos",
   "metadata": {},
   "outputs": [],
   "source": [
    "rainbow_colors = [\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"indigo\", \"violet\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eleven-explorer",
   "metadata": {},
   "source": [
    "\n",
    "We **don't** want:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aboriginal-denver",
   "metadata": {},
   "outputs": [],
   "source": [
    "rainbow_colors[0] = \"gray\"\n",
    "## Gray's not in the rainbow!\n",
    "rainbow_colors.pop()\n",
    "## We can't lose violet!\n",
    "rainbow_colors.append(\"pink\")\n",
    "# Pink's not in the rainbow!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "literary-disorder",
   "metadata": {},
   "source": [
    "\n",
    "We want `rainbow_colors` to be **immutable** - the list _cannot_ be changed.\n",
    "\n",
    "How we do that in Python?\n",
    "\n",
    "---\n",
    "\n",
    "## Introducing: Tuples\n",
    "\n",
    "**Sets** have the following properties:\n",
    "\n",
    "- No duplicates\n",
    "- Mutable\n",
    "\n",
    "**Tuples** are similar to a list with the following differences:\n",
    "\n",
    "- Allows duplicates (same as a list)\n",
    "- Once assigned, the tuple _cannot be changed_\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "competitive-latitude",
   "metadata": {},
   "outputs": [],
   "source": [
    "rainbow_colors_tuple = (\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"indigo\", \"violet\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cubic-prospect",
   "metadata": {},
   "source": [
    "\n",
    "When should you use a tuple?\n",
    "\n",
    "- When you need data protection through immutability (note: all Python variables are public).\n",
    "- When you never want to change the list.\n",
    "- Tuples are sometimes wrapped in a class namespace to simulate what would be done with a [const structure](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-define-constants) in a C-based language.\n",
    "- This is a way of holding appconstants, or constants your program will use (like the API endpoint of a server, credentials, etc.)\n",
    "\n",
    "---\n",
    "\n",
    "## Tuple Syntax\n",
    "\n",
    "- Created with parentheses `()`.\n",
    "- Access values via indices (like regular lists, but *not* like sets).\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "closed-tennessee",
   "metadata": {},
   "outputs": [],
   "source": [
    "rainbow_colors_tuple = (\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"indigo\", \"violet\")\n",
    "print(rainbow_colors[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "inner-stick",
   "metadata": {},
   "source": [
    "\n",
    "- Tuples can be printed with a `for` loop (just like a set or list!).\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "caroline-anniversary",
   "metadata": {},
   "outputs": [],
   "source": [
    "rainbow_colors_tuple = (\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"indigo\", \"violet\")\n",
    "\n",
    "for color in rainbow_colors_tuple:\n",
    "    print(color)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mysterious-daniel",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## We Do: Tuples\n",
    "\n",
    "Let's declare a tuple named `seasons` and set it to have the values `fall`, `winter`, `spring`, and `summer`. We'll print the tuple and each value. Then we'll try to reassign them (we can't)!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "committed-vector",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "occasional-agriculture",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Quick Review: Sets, Tuples, Lists\n",
    "\n",
    "**List**:\n",
    "\n",
    "- The original, normal object: `[\"red\", \"red\", \"yellow\", \"green\"]`.\n",
    "- Has duplicates; mutable: `append()`, `insert(index)`, `pop()`, `pop(index)`\n",
    "\n",
    "**Set**:\n",
    "\n",
    "- List without duplicates: `{\"red\", \"yellow\", \"green\"}`.\n",
    "- Mutable: `add()` and `remove(element)`\n",
    "\n",
    "**Tuple**:\n",
    "\n",
    "- Has duplicates, but immutable: You can't change it!\n",
    "- `(\"red\", \"red\", \"yellow\", \"green\")` will *always* be `(\"red\", \"red\", \"yellow\", \"green\")`.\n",
    "\n",
    "---\n",
    "\n",
    "## Quick Review: Sets, Tuples, Lists"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "black-spanish",
   "metadata": {},
   "outputs": [],
   "source": [
    "### Creation ###\n",
    "# List\n",
    "my_list = [\"red\",  \"yellow\", \"green\", \"red\"]\n",
    "# Sets\n",
    "my_set = {\"red\",  \"yellow\", \"green\"}\n",
    "my_set2 = set(my_list))\n",
    "my_set = set(a_list_to_convert)\n",
    "# Tuples\n",
    "my_tuple = (\"red\",  \"yellow\", \"green\")\n",
    "\n",
    "### Appending a New Value ###\n",
    "my_list.append(\"blue\")\n",
    "my_set.add(\"blue\")\n",
    "# Tuples -> You can't!\n",
    "\n",
    "### Removing items: ###\n",
    "my_list.pop(1)\n",
    "my_set.remove(\"red\")\n",
    "# Tuples -> You can't!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "prompt-glass",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Introducing Types\n",
    "\n",
    "Variables certainly can hold a lot!\n",
    "\n",
    "- Sets, tuples, and lists are easily confused.\n",
    "- `type()` tells us what a variable is: set, tuple, list, dictionary, integer, string - anything!\n",
    "\n",
    "Try it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "engaged-support",
   "metadata": {},
   "outputs": [],
   "source": [
    "unique_colors = set([\"red\", \"yellow\", \"green\", \"red\"])\n",
    "print(\"unique_colors is\", type(unique_colors))\n",
    "# --\n",
    "unique_colors_2 = [\"red\", \"yellow\", \"green\", \"red\"]\n",
    "print(\"unique_colors_2 is\", type(unique_colors_2))\n",
    "# --\n",
    "unique_colors_3 = (\"red\", \"yellow\", \"green\", \"red\")\n",
    "print(\"unique_colors_3 is\", type(unique_colors_3))\n",
    "# --\n",
    "my_number = 2\n",
    "print(\"my_number is\", type(my_number))\n",
    "# --\n",
    "my_string = \"Hello!\"\n",
    "print(\"my_string is\", type(my_string))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "unnecessary-tunnel",
   "metadata": {},
   "source": [
    "</aside>\n",
    "\n",
    "---\n",
    "\n",
    "## You Do: List Types Practice\n",
    "\n",
    "- Create a list (`[]`), set (`{}`), and tuple (`()`) of some of your favorite foods.\n",
    "- Create a second set from the list.\n",
    "\n",
    "Next, in every list type that you can:\n",
    "\n",
    "- Add `\"pizza\"` anywhere; append `\"eggs\"` to the end.\n",
    "- Remove `\"pizza\"`.\n",
    "- Re-assign the element at index `1` to be `\"popcorn\"`.\n",
    "- Remove the element at index `2` and re-insert it at index `0`.\n",
    "- Print the element at index `0`.\n",
    "\n",
    "Print your final lists using a loop, then print their types. Don't throw an error!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "drawn-imagination",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "collected-internet",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Summary and Q&A\n",
    "\n",
    "We've learned two new types of lists:\n",
    "\n",
    "Sets:\n",
    "\n",
    "- A mutable list without duplicates.\n",
    "- Handy for storing emails, usernames, and other unique elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "arbitrary-movie",
   "metadata": {},
   "outputs": [],
   "source": [
    "email_set = {'my_email@gmail.com', 'second_email@yahoo.com', \"third_email@hotmail.com\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aboriginal-omaha",
   "metadata": {},
   "source": [
    "\n",
    "Tuples:\n",
    "\n",
    "- An immutable list that allows duplicates.\n",
    "- Handy for storing anything that won't change.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "valid-trail",
   "metadata": {},
   "outputs": [],
   "source": [
    "rainbow_tuple = (\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"indigo\", \"violet\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "specialized-ribbon",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Additional Reading\n",
    "\n",
    "- [Repl.it that recaps Tuples](https://repl.it/@GAcoding/python-programming-tuple-practice?lite=true)\n",
    "- [Python Count Occurrences of Letters, Words and Numbers in Strings and Lists-Video](https://www.youtube.com/watch?v=szIFFw_Xl_M)\n",
    "- [Storing Multiple Values in Lists](https://swcarpentry.github.io/python-novice-inflammation/03-lists/)\n",
    "- [Sets and Frozen Sets](https://www.python-course.eu/sets_frozensets.php)\n",
    "- [Sets](https://www.learnpython.org/en/Sets)\n",
    "- [Python Tuple](https://www.programiz.com/python-programming/tuple)\n",
    "- [Tuples](http://openbookproject.net/thinkcs/python/english3e/tuples.html)\n",
    "- [Strings, Lists, Tuples, and Dictionaries Video](https://www.youtube.com/watch?v=19EfbO5D_8s)\n",
    "- [Python Data Structures: Lists, Tuples, Sets, and Dictionaries Video](https://www.youtube.com/watch?v=R-HLU9Fl5ug)\n"
   ]
  }
 ],
 "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.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
