{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "dedicated-grammar",
   "metadata": {},
   "source": [
    "<!--\n",
    "title: Modules and Libraries\n",
    "type: lesson\n",
    "duration: \"00:40\"\n",
    "creator: Brandi Butler\n",
    "-->\n",
    "\n",
    "<h1>Modules and Packages</h1>\n",
    "\n",
    "\n",
    "<!--\n",
    "\n",
    "## Overview\n",
    "This lesson walks through the idea of modules, using the `random` module to look at documentation and methods. Then, it segues into a few longer exercises with PyTime.\n",
    "\n",
    "## Important Notes or Prerequisites\n",
    "\n",
    "Libraries were covered extremely briefly in the pre-work (in the Python Introduction lesson), so you can call back to that. They've also used itertools, so you can reference that. This is just a small taste of the many, many modules out there. Highly encourage students to explore more on their own!\n",
    "\n",
    "## Learning Objectives\n",
    "In this lesson, students will:\n",
    "\n",
    "* Add packages and modules to a Python program.\n",
    "* Create a program utilizing Pytime.\n",
    "* Navigate library documentation.\n",
    "\n",
    "\n",
    "\n",
    "## Duration\n",
    "40 minutes.\n",
    "\n",
    "### Notes on Timing\n",
    "\n",
    "It would be easy to get carried away and spend a lot of time either playing around with the modules or reading through the docs. Keep an eye on the clock and move on to the next topic once you've covered a few basic examples. The goal is to understand modules, not to become a pro at any particular one.\n",
    "\n",
    "### Use the Parking Lot!\n",
    "\n",
    "Since there are many modules, students may start asking questions along the lines of `Hey, have you used the XXX module?` These are great questions as they reveal a lot of the student's passion and interest! Insofar as possible, try to answer those questions! If you find yourself running short of time, however, write the module name down in the parking lot so you can follow up with that student during a lab or a break.\n",
    "\n",
    "## Suggested Agenda\n",
    "\n",
    "| Time | Activity |\n",
    "| --- | --- |\n",
    "| 0:00 - 0:03 | Welcome |\n",
    "| 0:04 - 0:24 | Exploring Modules |\n",
    "| 0:24 - 0:42 | Pytime Module |\n",
    "| 0:42 - 0:45 | Summary |\n",
    "\n",
    "## Differentiation and Extensions\n",
    "- Don't let slower students be frustrated if they're hung up on a particular function. The main point is that there are other files that they can use that have functions - that's really it.\n",
    "- For more advanced students, encourage them to experiment with other functions in the modules.\n",
    "\n",
    "## In Class: Materials\n",
    "- Projector\n",
    "- Internet connection\n",
    "- Python3\n",
    "-->\n",
    "\n",
    "---\n",
    "\n",
    "## Lesson Objectives\n",
    "*After this lesson, you will be able to...*\n",
    "\n",
    "* Add packages and modules to a Python program.\n",
    "* Create a program utilizing PyTime.\n",
    "* Navigate library documentation.\n",
    "\n",
    "\n",
    "---\n",
    "\n",
    "## Discussion: Let's Dive In\n",
    "\n",
    "What do you think these have in common?\n",
    "\n",
    "- A collection of mathematical functions? \n",
    "- A Python function that tells us when Mother's Day is.\n",
    "- A Python function that gets all the contents of a webpage for us.\n",
    "\n",
    "---\n",
    "\n",
    "\n",
    "## What is a Module?\n",
    "\n",
    "Answer: They're all available to us via modules! (In fact, `math` IS a module).\n",
    "\n",
    "Modules are collections of useful Python code and functions that we can use.\n",
    "\n",
    "- This is much like a class that someone else has written.\n",
    "- It's free - less work for us!\n",
    "\n",
    "Use a function by `import <module>` at the top of your code, then `<module>.function_you_want()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "digital-charger",
   "metadata": {},
   "outputs": [],
   "source": [
    "# import < module name > - brings in the module file, so we can use it.\n",
    "import math\n",
    "\n",
    "num = 9\n",
    "\n",
    "# maths.sqrt : \"Look in the math module, and use the sqrt function\"\n",
    "print(math.sqrt(num))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "regulated-fifth",
   "metadata": {},
   "source": [
    "**Pro Tip**: Check the Additional Reading at the end of the lesson to see how to write your own module!\n",
    "\n",
    "- A **module**, according to the [Python Docs](https://docs.python.org/3/tutorial/modules.html), \"is a file containing Python definitions and statements. The file name is the module name with the suffix `.py` appended.\n",
    "- You will encounter many modules that others have written. They are free-to-use and you can think of them as extensions of Python's functionality.\n",
    "\n",
    "---\n",
    "\n",
    "## Python Standard Library\n",
    "\n",
    "We're going to look at several different modules to get you used to them.\n",
    "\n",
    "The [Python Standard Library](https://docs.python.org/3/library/) bundles all common modules, so we can just `import` (use) them.\n",
    "\n",
    "We've seen the `math` module already. Let's look at another module, `random`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "gentle-result",
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "# Done! Now we can use any functions in the random module!\n",
    "\n",
    "# randint is a function in the random module\n",
    "my_random_number = random.randint(2,8)\n",
    "\n",
    "# This could be 2, 3, 4, 5, 6, 7, or 8\n",
    "print(my_random_number)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "vertical-tower",
   "metadata": {},
   "source": [
    "- This means that they are so commonly used, that they are already included and you don't have to download them separately.\n",
    "- If you want to use any functions from a module in the standard library, all you need to do is include an import statement for that module at the top of your file.\n",
    "\n",
    "---\n",
    "\n",
    "## We Do: Let's Import Random\n",
    "\n",
    "\n",
    "Restart your kernel and run the code below. What happened? Why?\n",
    "\n",
    "Uncomment the first line: `import random`. Run it again. Try changing the values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "challenging-transsexual",
   "metadata": {},
   "outputs": [],
   "source": [
    "# import random\n",
    "# Done! Now we can use the random module all we want!\n",
    "\n",
    "# randint is a function in the random module\n",
    "my_random_number = random.randint(2,8)\n",
    "\n",
    "# This could be 2, 3, 4, 5, 6, 7, or 8\n",
    "print(my_random_number)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "brutal-switzerland",
   "metadata": {},
   "source": [
    "</aside>\n",
    "\n",
    "---\n",
    "\n",
    "## We do: Exploring the Random Module\n",
    "\n",
    "How do we know:\n",
    "\n",
    "- What `randint` does?\n",
    "- What the `random` module has?\n",
    "\n",
    "Every module has documentation, which has:\n",
    "\n",
    "- What functions are in the module.\n",
    "- How to use them.\n",
    "\n",
    "Here is the <a href=\"https://docs.python.org/3/library/random.html\" target=\"\\_blank\">documentation for the random module</a>.\n",
    "\n",
    "- Can you find our `randint` function?\n",
    "\n",
    "---\n",
    "\n",
    "## Exercise: Random Numbers\n",
    "\n",
    "- Find the `random` function in the <a href=\"https://docs.python.org/3/library/random.html\" target=\"\\_blank\">documentation</a>. (Yes, a function can have the same name as the module).\n",
    "- Print out a randomly generated number using `random()`.\n",
    "- Run the program several times; is your random number different every time?\n",
    "* Why do you think this is useful?\n",
    "\n",
    "> **Protip**: The `[`, in mathematics means `inclusive`, whereas the `)` means `exclusive`. Thus the possible values include 0.0, but do **not** include 1.0!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "military-address",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "cardiovascular-husband",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Quick Review\n",
    "\n",
    "Modules are collections of useful Python code and functions that we can use.\n",
    "\n",
    "Use a function by `import <module>` at the top of your code, then `<module>.function_you_want()`.\n",
    "\n",
    "We've looked at two modules: `math` and `random`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "hispanic-living",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import statements go at the top of your file\n",
    "import math\n",
    "import random\n",
    "\n",
    "# Using the randint function in the random module\n",
    "my_random_number = random.randint(2,8)\n",
    "print(my_random_number)\n",
    "\n",
    "# Using sqrt function to take the square root of a number\n",
    "num = 81\n",
    "print(math.sqrt(num))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "surface-myanmar",
   "metadata": {},
   "source": [
    "\n",
    "The [Python Standard Library](https://docs.python.org/3/library/) bundles all common modules, so we can just `import` (use) them.\n",
    "\n",
    "**Next up:** More `random` module practice.\n",
    "\n",
    "---\n",
    "\n",
    "## We Do: Do You Feel Lucky?\n",
    "\n",
    "\n",
    "How could you pick a random value from a list? The `random` module has a function called `choice` - it works on any non-empty list.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "burning-revolution",
   "metadata": {},
   "outputs": [],
   "source": [
    "people_in_lottery = [\"Tina\", \"Batu\", \"Gina\", \"Jim\", \"Andres\"]\n",
    "lottery_winner = random.choice(people_in_lottery)\n",
    "print(lottery_winner, \"wins a new car!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "compound-lawrence",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Exercise: Let's Get Random!\n",
    "\n",
    "- Generate a random number with `random.randrange()`. Print it out.\n",
    "- Create a list, like `deck = [\"ten\", \"jack\", \"queen\", \"king\", \"ace\"]`\n",
    "- Use `random.choice()` to pick a random card in your deck. Print it out.\n",
    "- Use `random.shuffle()` to mix up your deck; print the shuffled deck out. Be sure to check the documentation for this method!\n",
    "\n",
    "Here is the <a href=\"https://docs.python.org/3/library/random.html\" target=\"\\_blank\">documentation for the random module</a>, so you can look up functions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "excess-mercury",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "varied-ordinance",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## What is a Package?\n",
    "\n",
    "A package, also called a **library**, is  a place where one or more related modules are stored.\n",
    "\n",
    "- In technical terms, *one or more* modules bundled together under a single namespace.\n",
    "- A package is like a folder, while a module is like a file.\n",
    "\n",
    "\n",
    "The [Python Standard Library](https://docs.python.org/3/library/) bundles all common modules - it's the package with `math` and `random` modules inside it.\n",
    "\n",
    "**All packages are modules, but not all modules are packages.**\n",
    "\n",
    "- Both `library` and `package` are technically correct and we can use the terms interchangeably.\n",
    "- PyTime is an interesting example of a package, because it only has one module in it.\n",
    "\n",
    "---\n",
    "\n",
    "## We Do: ModuleNotFoundError\n",
    "\n",
    "\n",
    "The Python Standard Library has a [huge list](https://docs.python.org/3/library/index.html) of modules. But not every Python module in the world is part of it!\n",
    "\n",
    "`pytime` is a non-standard module. PyTime can:\n",
    "\n",
    "* Get dates, date ranges, and times.\n",
    "* Find the date of a particular holiday.\n",
    "\n",
    "Run the following code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "outstanding-parks",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pytime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "rough-kennedy",
   "metadata": {},
   "source": [
    "\n",
    "What's happened?\n",
    "\n",
    "`ModuleNotFoundError`:\n",
    "\n",
    "- The module isn't part of the standard library.\n",
    "- If we want to use modules from other packages, we'll have to tell Python that those packages exist.\n",
    "\n",
    "---\n",
    "\n",
    "\n",
    "## Including PyTime\n",
    "\n",
    "When importing from the standard library, the package is implied:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "buried-indication",
   "metadata": {},
   "outputs": [],
   "source": [
    "# (from standard) import MODULE\n",
    "import random"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "minor-shareware",
   "metadata": {},
   "source": [
    "\n",
    "Otherwise, you need to specify the package!\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "capital-sample",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from PACKAGE import MODULE\n",
    "from pytime import pytime\n",
    "\n",
    "# The names don't need to be the same:\n",
    "from pygame import joystick\n",
    "# Yes - that's real!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "viral-recorder",
   "metadata": {},
   "source": [
    "> **Protip**: Remember that *package* means *library*!\n",
    "\n",
    "- Because pytime is a package, we need to import the pytime module FROM the pytime package. It's a little confusing because they have the same name! But as you'll see in a moment, in the code itself, one is a folder name and the other is a file name.\n",
    "- You can see with joystick and pygame that modules and packages don't need to have the same name.\n",
    "\n",
    "---\n",
    "\n",
    "## Installing PyTime\n",
    "\n",
    "New packages need to be installed.\n",
    "\n",
    "- Let's install `pytime`.\n",
    "\n",
    "First, let's double check something:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "twelve-claim",
   "metadata": {},
   "outputs": [],
   "source": [
    "# the '!' tells jupyter to run this code in the shell rather than in Python\n",
    "# the output should have Anaconda3 somewhere in the path\n",
    "!which pip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "enabling-logic",
   "metadata": {},
   "outputs": [],
   "source": [
    "# install the pytime package\n",
    "!pip install pytime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "experimental-summary",
   "metadata": {},
   "source": [
    "Once that's successful, try again to run your file.\n",
    "\n",
    "> **Protip**: `pip` stands for `Pip Installs Packages`. `pip3` uses Python3."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "compressed-professional",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pytime import pytime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "capable-comparison",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## PyTime Holidays\n",
    "\n",
    "Let's explore PyTime:\n",
    "\n",
    "- Scan the <a href=\"https://github.com/shinux/PyTime\" target=\"\\_blank\">PyTime docs</a>, to find the `mother` function.\n",
    "\n",
    "When was Mother's Day in 2016?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "detailed-aurora",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "broadband-prototype",
   "metadata": {},
   "source": [
    "\n",
    "What about this year?\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "labeled-cream",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "abandoned-exercise",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## PyTime Documentation\n",
    "\n",
    "Here are some examples of PyTime in action:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dynamic-excitement",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(pytime.father())              # Father's Day without a year (defaults to current year, so this example was generated in 2021)\n",
    "print(pytime.mother(2016))          # 2016 Mother's Day\n",
    "print(pytime.easter(1999))          # 1999 Easter"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "friendly-objective",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Quick Review\n",
    "\n",
    "Not all modules are in the standard library. If you try to import a module Python doesn't recognize, you'll get a `ModuleNotFoundError`.\n",
    "\n",
    "When importing from the standard library, the package is implied:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "secondary-horizontal",
   "metadata": {},
   "outputs": [],
   "source": [
    "# (from standard) import MODULE\n",
    "import random"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "white-fever",
   "metadata": {},
   "source": [
    "\n",
    "Otherwise, you need to specify the package!\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "wrapped-executive",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from PACKAGE import MODULE\n",
    "from pytime import pytime\n",
    "from pygame import joystick"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "steady-acquisition",
   "metadata": {},
   "source": [
    "\n",
    "If you're using a non-standard package like `pytime` or `pygame`, you'll have to also install it.\n",
    "\n",
    "You can use the website repl.it for testing small pieces of code - it has packages installed.\n",
    "\n",
    "---\n",
    "\n",
    "## Summary and Q&A\n",
    "\n",
    "Modules are `.py` files with functions. They're written by other people for us to use!\n",
    "\n",
    "- A packages (a.k.a. library) is a bundle of one or more modules.\n",
    "- Python's standard library has a lot of common modules! `random`, `math`, etc.\n",
    "- Nonstandard libraries need to be installed (`pip install pytime`).\n",
    "\n",
    "To use modules, at the top of your file, put:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "valuable-seattle",
   "metadata": {},
   "outputs": [],
   "source": [
    "# From the standard library: `import MODULE`\n",
    "import random\n",
    "\n",
    "# From non-standard packages: `from PACKAGE import MODULE`\n",
    "from pytime import pytime\n",
    "\n",
    "# And preface your function with the module name.\n",
    "mothers_day = pytime.mother(2016) # 2016-05-08"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "accepted-mongolia",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Additional Resources\n",
    "\n",
    "* [Python Modules](https://docs.python.org/3/tutorial/modules.html)\n",
    "* [Python's Standard Library](https://docs.python.org/3/library/index.html)\n",
    "* [Write a module in python 3 - Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-write-modules-in-python-3)\n",
    "* [Math](https://docs.python.org/3/library/math.html)\n",
    "* [Random](https://docs.python.org/3/library/random.html)\n",
    "* [PyTime](https://pypi.org/project/pytime/)\n",
    "* [List of Commonly Used Packages](https://pythontips.com/2013/07/30/20-python-libraries-you-cant-live-without/)\n",
    "* [Useful Modules by Discipline](https://wiki.python.org/moin/UsefulModules)\n",
    "* [Further Reading](https://www.learnpython.org/en/Modules_and_Packages)\n",
    "* [Formatting Datetime](https://docs.python.org/3.0/library/datetime.html#strftime-behavior)\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
}
