{ "metadata": { "kernelspec": { "codemirror_mode": { "name": "ipython", "version": 2 }, "display_name": "IPython (Python 2)", "language": "python", "name": "python2" }, "name": "", "signature": "sha256:7cf277e28b0242bd51b679f9211a88c2100b7c34ff7fd7977b2ad160b75c9df3" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Introductions: Hi, I'm .... I'll be co-facilitating 'Programming with Python' with [our mentors names] and [our volunteers names]. If you would like to follow along and type in some of the snippets of code that we demo, our volunteers can assist you in setting up your computer. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's begin by giving a quick recap on what we did in the earlier workshops today. In the first workshop we learned about numbers, variables, strings, booleans, and making choices with the use of if-statements. In the second workshop we added lists and looping to our skills. Along the way we used a few functions, such as the built-in functions, print() and len()." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this workshop, we're going to go a little further in depth into functions and Python modules." ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have already seen a few functions (recall len() for calculating list and string lengths and sum() for summing lists).\n", "\n", "Python also lets us make our own functions." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Example: Greeting Script" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's write our first Python script. Create a file called `birthday.py`. Put the following line into the file. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(\"Happy Birthday, dear Carol!\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now you have a program that simply prints a happy birthday greeting for Carol.\n", "\n", "It's not Carol's birthday, but let's run this program anyway, just to confuse her in good fun ;)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%bash\n", "python3 greeting.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can make this code into a function like so. Let's take a quick look at what we have here." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def happy_birthday_carol():\n", " print(\"Happy Birthday, dear Carol!\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Examine the function in detail" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The top part is the *header* of the function. The header contains the keyword, 'def', the name of the function, a parameter, and a colon.\n", "\n", "`def` is short for *define*. It's the Python keyword used to indicate the start of a function definition.\n", "\n", "`happy_birthday_carol` is the name of the function.\n", "\n", "This is a function with no parameters.\n", "\n", "The body of our function contains one print line. We need to indent this line, and any other lines of code in a function's body, by 4 spaces." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Let's call the function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that nothing was printed out after we defined our function. To use our function we need to call it, like this:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday_carol()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Don't forget those parentheses. \n", "\n", "Without the parentheses, Python wouldn't know that we were trying to call our function, and will print out the value of the thing called `happy_birthday_carol`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday_carol" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, the Python interpreter is basically saying, \"The value of happy_birthday_carol is a function.\"" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Let's define and call another function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That function printed a nice greeting for Carol. But Rise's now feeling left out. Let's define a function for her too." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def happy_birthday_rise():\n", " print(\"Happy Birthday, dear Rise!\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's call the function:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday_rise()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Refactor time!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, now, let's work on reusing our code so that we reduce code duplication.\n", "\n", "Wouldn't it be cool if we could pass a name into our function so we don't need to write a different function for every name?\n", "\n", "Python allows us to do just that with function parameters. We can add a parameter by typing a variable name in between the parethesis after our function name. We can then use the parameter variable in our function.\n", "\n", "We'll create a new function called `happy_birthday`, and add a parameter, `name`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def happy_birthday(name):\n", " print(\"Happy Birthday, dear \" + name + \"!\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we are concatenating 3 strings:\n", "* \"Happy Birthday, dear \"\n", "* whatever the value of `name` is (Note: for the purposes of this example, let's assume that we're always getting a string)\n", "* \"!\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To execute or run our new function, we simply call it by its name, `happy_birthday`, and pass a value in between the parenthesis, such as the string `Trey`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday(\"Trey\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Calling it over and over in a loop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's get a little bolder and make a list of names that we can loop over and then pass each one into our `happy_birthday` function. What we get is the same results as the other earlier lines of code!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "names = [\"Carol\", \"Rise\", \"Trey\", \"Alain\"]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "for name in names:\n", " happy_birthday(name)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Exercise: Try to break `happy_birthday()`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1) Try calling `happy_birthday()` with other values, such as:\n", "* A really, really, really long name\n", "* Something ridiculous that makes no sense grammatically\n", "* Numbers\n", "* Other Python types, if you know about any other ones\n", "\n", "This is how malicious \"black hat\" hackers think when they try to break into desktop and web applications.\n", "\n", "2) Try adding a bad list item to `names`. Experiment with the position of the bad item." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Example: Better String Formatting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rather than using string concatenation, let's use a string formatting operator that doesn't care what type of value it receives." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def happy_birthday(name):\n", " print(\"Happy Birthday, dear {0}!\".format(name))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, the function can print happy birthday greetings for any value of `name`, even for people with bizarre names like:\n", "* 100\n", "* 3.1415927\n", "* \u01ac\u0335\u032c\u030a (The Artist Formerly Known As Prince)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday(100)\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday(3.1415927)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "happy_birthday(\"\u01ac\u0335\u032c\u030a\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's better to use `format()` just in case `name` isn't guaranteed to be a string." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Advanced Exercise: Why not use `str()` like this?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def happy_birthday(name):\n", " print(\"Happy Birthday, dear \" + str(name) + \"!\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Answer: You can, but keep in mind that this only works on Python 3:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "str(u'\\xff')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now you have some advanced knowledge about how Python 3 handles Unicode better than Python 2!" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Example: Getting Fancy With Math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What about a function that does some math for us?\n", "\n", "Every year on my birthday, I like to figure out what numbers are divisible by my new age. That is, the factors of my age:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def print_factors(age):\n", " for i in range(1, age + 1):\n", " if age % i == 0:\n", " print(i)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This year, I turned 32." ] }, { "cell_type": "code", "collapsed": false, "input": [ "print_factors(32)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "From the output of `print_factors()`, I now know that I'm:\n", "* Twice as old as a 16-year-old\n", "* Four times as old as an 8-year-old\n", "* Eight times as old as a 4-year-old\n", "* Sixteen times as old as a 2-year-old\n", "\n", "How is this useful? Well, the next time a 4-year-old bullies me, I'm going to say, \"Watch it, I'm exactly eight times as old as you.\"\n", "\n", "Next year, I'll be able to brag to 3-year-olds: \"Ha ha ha, I'm exactly eleven times as old as you.\"" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print_factors(33)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Example: Cupcake Tally" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So far we've explored functions that:\n", "* Take strings or other values as input\n", "* Print strings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's create a new function, `cupcake_tally()`. This function will be different from the others that I covered. Rather than just printing stuff, it'll return a value when called.\n", "\n", "A good birthday party should allocate:\n", "* 2 cupcakes per guest\n", "* 13 cupcakes for the birthday person, because if it's your birthday, you should be allowed to eat a baker's dozen of cupcakes." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def cupcake_tally(guests):\n", " \"\"\" Given number of party guests, returns how many cupcakes are needed. \"\"\"\n", " return 2 * guests + 13" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How many cupcakes do we need for a party with 30 guests?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "cupcake_tally(30)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What about if I'm celebrating my birthday at home with just my husband, Daniel?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "cupcake_tally(guests=1)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ooh, 15 cupcakes sounds about right for our little party, yeah? ;)\n", "\n", "Notice how we explicitly named the `guests` parameter in that example." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Printing the return value" ] }, { "cell_type": "code", "collapsed": false, "input": [ "cupcakes = cupcake_tally(10)\n", "print(\"We need to make {0} cupcakes.\".format(cupcakes))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We call our function, `cupcake_tally()`, and pass in 10 as the value of `guests`. \n", "\n", "`cupcake_tally(10)` returns 33, which gets stored in the `cupcakes` variable.\n", "\n", "Lastly, we print \"We need to make 33 cupcakes.\" using Python string formatting." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Multiple function arguments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's talk about one last thing that functions can do and that is, they can be given more than one parameter. Let's demonstrate this by passing 2 parameters to our cupcake function.\n", "\n", "We want to be able to specify the number of cupcakes each guest will eat. Let's change our function to accept two parameters:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def cupcake_tally(cupcakes, guests): \n", " return cupcakes * guests + 13" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "cupcake_tally(4, 15)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that we have 2 parameters now: `cupcakes` and `guests`\n", "\n", "Our function is called and passes in two values of 4 and 15. It returns 73." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Summary: What are functions used for?" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Program decomposition, or factoring" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To break down a problem into parts. It makes the code more readable and is easier to understand." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Code reuse" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions can be used instead of repeating the same lines of code at different times throughout a program. This reduces duplication of code." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Abstraction or simplification" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using functions allows us to hide all of the details involved and put them into one place and simply call the function to execute the lines of code." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Exercise: Why are functions useful?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, create a new Python script and type in the following." ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(\"On the day of Sept 20, 2014, were you at Intro to Python?\")\n", "answer = input(\"Answer truthfully, yes or no --> \")\n", "if answer == \"no\":\n", " answer = input(\"Are you sure that you weren't? Tell the truth, now --> \")\n", "\n", "print(\"Were you thinking of skipping the workshop to go to Sea World?\")\n", "answer = input(\"Answer truthfully, yes or no --> \")\n", "if answer == \"no\":\n", " answer = input(\"Are you sure that you weren't? Tell the truth, now --> \")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Look up when you're done, so that we know to move on to the next step." ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Was this annoying?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Raise your hand if you felt like this exercise was repetitive...TODO" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Modules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Modules are used to make a programmer's life easier. A module is used to group functions, variables, and other things together in an understandable bundle.\n", "\n", "Python comes with lots of modules built-in. For example there's a random module for generating random numbers. Let's import it so we can use some of its functions:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import random" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The [random](https://docs.python.org/3.4/library/random.html) module has a [randint](https://docs.python.org/3.4/library/random.html?highlight=randint#random.randint) function which takes two parameters. randint will return a random integer in between (or including) the two parameters. For example we can generate a random number between 1 and 6." ] }, { "cell_type": "code", "collapsed": false, "input": [ "random.randint(1, 6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 10, "text": [ "2" ] } ], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's use the random integer function to simulate rolling a die in a game" ] }, { "cell_type": "code", "collapsed": false, "input": [ "vegas_die_1 = random.randint(1, 6)\n", "vegas_die_2 = random.randint(1, 6)\n", "print(\"First die: \" + str(vegas_die_1))\n", "print(\"Second die: \" + str(vegas_die_2))\n", "print(\"You rolled a \" + str(vegas_die_1 + vegas_die_2))" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "First die: 3\n", "Second die: 3\n", "You rolled a 6\n" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "choice is a function in the random module that returns a random item from a given list or string" ] }, { "cell_type": "code", "collapsed": false, "input": [ "random.choice('abcdefghijklmnopqrstuvwxyz')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 13, "text": [ "'m'" ] } ], "prompt_number": 13 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We could use random.choice to wish happy birthday to a random friend." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's make a function random_happy_birthday that takes a list of names and wishes a random person happy birthday" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def random_happy_birthday(names):\n", " name = random.choice(names)\n", " happy_birthday(name)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 14 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's try it out with a list of names:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "random_happy_birthday([\"Alain\", \"Carol\", \"Rise\", \"Trey\"])" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Happy Birthday, dear Carol!\n" ] } ], "prompt_number": 20 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Modules and functions can make things really simple to do. For example we could in a few lines of code get and display a YouTube video" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython.display import YouTubeVideo\n", "# a tutorial about Python at PyCon 2014 in Montreal, Canada by Jessica McKellar\n", "YouTubeVideo('MirG-vJOg04')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", " \n", " " ], "metadata": {}, "output_type": "pyout", "prompt_number": 11, "text": [ "" ] } ], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }