{ "metadata": { }, "nbformat": 4, "nbformat_minor": 5, "cells": [ { "id": "metadata", "cell_type": "markdown", "source": "
\n\n# Python - Functions\n\nby [The Carpentries](https://training.galaxyproject.org/hall-of-fame/carpentries/), [Helena Rasche](https://training.galaxyproject.org/hall-of-fame/hexylena/), [Donny Vrins](https://training.galaxyproject.org/hall-of-fame/dirowa/), [Bazante Sanders](https://training.galaxyproject.org/hall-of-fame/bazante1/)\n\nCC-BY licensed content from the [Galaxy Training Network](https://training.galaxyproject.org/)\n\n**Objectives**\n\n- How do I write functions in Python?\n- What is a function?\n- What do they look like?\n- Fill in the missing part of a function\n\n**Objectives**\n\n- Understand the structure of a \"function\" in order to be able to construct their own functions and predict which functions will not work.\n\n**Time Estimation: 30M**\n
\n", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-0", "source": "

Functions are the basic unit of all work in Python! Absolutely everything you do uses functions. Conceptually, functions are super simple. Just like in maths, they take an input, do some transformation, and return an output. As an example, f(x) = x + 2 is a function that calculates whatever value you request, plus two. But functions are foundational, so, you should understand them well before moving on.

\n
\n

Agenda

\n

In this tutorial, we will cover:

\n
    \n
  1. What is a Function
  2. \n
  3. Create Functions
  4. \n
\n
\n

What is a Function

\n

Functions are a way to re-use some computation you want to do, multiple times. If you don’t have a function, you need to re-write the calculation every time, so we use functions to collect those statements and make them easy to re-run. Additionally they let us “parameterise” some computation. Instead of computing the same value every time, we can template it out, we can re-run the computation with new inputs, and see new results.

\n
\n
\n

⌨️ Math

\n
# Define our function\nf(x) = 3 * x\n# Compute some value\nf(3) # is 9\n
\n
\n
\n

🖥 Python

\n
# Define our function\ndef f(x):\n   return 3 * x\n# Compute some value\nf(3)\n
\n
\n
\n

We’ve talked about mathematical functions before, but now we’ll talk about more programing-related functions

\n

Create Functions

\n

Human beings can only keep a few items in working memory at a time. Breaking down larger/more complicated pieces of code in functions helps in understanding and using it. A function can be re-used. Write one time, use many times. (Known as staying Don’t Repeat Yourself (DRY) in the industry.)

\n

Knowing what Americans mean when they talk about temperatures and weather can be difficult, but we can wrap the temperature conversion calculation (\\(^{\\circ}\\text{C} = (^{\\circ}\\text{F} - 32) * \\dfrac{5}{9}\\)) up as a function that we can easily re-use.

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-1", "source": [ "def fahr_to_celsius(temp):\n", " return ((temp - 32) * (5/9))" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-2", "source": "

\"The

\n

The function definition opens with the keyword def followed by the name of the function fahr_to_celsius and a parenthesized list of parameter names temp. The body of the function — the statements that are executed when it runs — is indented below the definition line. The body concludes with a return keyword followed by the return value.

\n

When we call the function, the values we pass to it are assigned to those variables so that we can use them inside the function. Inside the function, we use a return statement to send a result back to whoever asked for it.

\n

Let’s try running our function.

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-3", "source": [ "fahr_to_celsius(32)\n", "print(f\"freezing point of water: {fahr_to_celsius(32)}C\")\n", "print(f\"boiling point of water: {fahr_to_celsius(212)}C\")" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-4", "source": "
\n

💡 Formatting Strings

\n

There are several ways to print out a few values in python. We’d recommend you to use f-strings as it’s the cleanest and most modern way to do it.

\n

f-strings start with an f (very descriptive name eh?). Within the text between the single or double quotes ('/\") you can use curly braces to refer to variables or python code which will be placed there in the string.

\n
a = 10\nb = f\"Here is the value of a: {a}\"\nprint(b)\nprint(f\"Here is the value of a: {5 + 5}\")\nprint(f\"Here is the value of a: {function_that_returns_10()}\")\n
\n

All of those would print out Here is the value of a: 10.

\n

f-strings can be a lot fancier for formatting decimal places, but we don’t need that for now. Just know:

\n
    \n
  1. Start with an f
  2. \n
  3. Use braces to use the value of a variable, a function, or some python expression.
  4. \n
\n
\n

We’ve successfully called the function that we defined, and we have access to the value that we returned.

\n

Now that we’ve seen how to turn Fahrenheit into Celsius, we can also write the function to turn Celsius into Kelvin:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-5", "source": [ "def celsius_to_kelvin(temp_c):\n", " return temp_c + 273.15\n", "\n", "print(f'freezing point of water in Kelvin: {celsius_to_kelvin(0.)}')" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-6", "source": "
\n

💡 Tip: What is 0.

\n

That’s a float! A . in a number makes it a float, rather than an integer.

\n
\n

What about converting Fahrenheit to Kelvin? We could write out both formulae, but we don’t need to. Instead, we can compose the two functions we have already created:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-7", "source": [ "def fahr_to_kelvin(temp_f):\n", " temp_c = fahr_to_celsius(temp_f)\n", " temp_k = celsius_to_kelvin(temp_c)\n", " return temp_k\n", "\n", "print(f'boiling point of water in Kelvin: {fahr_to_kelvin(212.0)}')" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-8", "source": "

This is our first taste of how larger programs are built: we define basic operations, then combine them in ever-larger chunks to get the effect we want. Real-life functions will usually be larger than the ones shown here — typically half a dozen to a few dozen lines — but they shouldn’t ever be much longer than that, or the next person who reads it won’t be able to understand what’s going on.

\n

Documentation

\n

Documenting your code is extremely, extremely, extremely important to do. We all forget what we’re doing, it’s only normal, so documenting what you’re doing is key to being able to restart work later.

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-9", "source": [ "def fahr_to_kelvin(temp_f):\n", " \"\"\"\n", " Converts a temperature from Fahrenheit to Kelvin\n", "\n", " temp_f: the temperature in Fahrenheit\n", "\n", " returns the temperature in Celsius\n", " \"\"\"\n", " temp_c = fahr_to_celsius(temp_f)\n", " temp_k = celsius_to_kelvin(temp_c)\n", " return temp_k\n", "\n", "print(f'boiling point of water in Kelvin: {fahr_to_kelvin(212.0)}')" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-10", "source": "

For a function this small, with such a descriptive name (fahr_to_kelvin) it feels quite obvious what the function should do, what inputs it takes, what outputs it produces. However

\n
\n

❓ Question: Converting statements to functions

\n

A lot of what you’ll do in programing is to turn a procedure that you want to do, into statements and a function.

\n

Fill in the missing portions of this function, two average numbers. Then use it to find the average of 32326 and 631

\n
\n
Hint: Select the text with your mouse to see the answer

👁 Solution

\n
def average2(a, b):\n    c = (a + b) / 2\n    return c\n
\n
\n
\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-11", "source": [ "# Test out solutions here!\n", "def average2(a, b):\n", " c =\n", " return c\n", "\n", "print(average2(32326, 631))" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-12", "source": "
\n

❓ Question: A more complicated example

\n

The formula for a 90° triangle can be expressed as: \\(c = \\sqrt{a^2 + b^2}\\)

\n
    \n
  1. Write a function which takes a and b, and calculates c
  2. \n
  3. Name this function “pythagorus”
  4. \n
  5. Remember to import math, if you haven’t already
  6. \n
\n
\n
Hint: Select the text with your mouse to see the answer

👁 Solution

\n
def pythagorus(a, b):\n    c = math.sqrt(math.pow(a, 2) + math.pow(b, 2))\n    return c\n
\n
\n
\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-13", "source": [ "# Test out solutions here!\n", "\n", "\n", "print(pythagorus(1234, 4321)) # Should return 4493.750883170984" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-14", "source": "

Variable Scope

\n

In composing our temperature conversion functions, we created variables inside of those functions, temp, temp_c, temp_f, and temp_k. We refer to these variables as local variables because they no longer exist once the function is done executing. If we try to access their values outside of the function, we will encounter an error:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-15", "source": [ "print(f'Again, temperature in Kelvin was: {temp_k}')" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-16", "source": "

If you want to reuse the temperature in Kelvin after you have calculated it with fahr_to_kelvin, you can store the result of the function call in a variable:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-17", "source": [ "temp_kelvin = fahr_to_kelvin(212.0)\n", "print(f'temperature in Kelvin was: {temp_kelvin}')" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-18", "source": "

Watch out for scope issues:

\n\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-19", "source": [ "a = 1\n", "b = 2.0\n", "\n", "# Location 1\n", "\n", "def some_generic_computation(x, y):\n", " c = x + y\n", " d = x * y\n", " e = c / d\n", " # Location 2\n", " return e\n", "\n", "# Location 3" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-20", "source": "
\n

❓ Question: Scope

\n

Given the above code, which variables are accessible at Locations 1, 2, and 3?

\n
\n
Hint: Select the text with your mouse to see the answer

👁 Solution

\n
    \n
  1. a, b
  2. \n
  3. a and b are there but you shouldn’t use these. x, y, c, d, e are also accessible.
  4. \n
  5. a, b.
  6. \n
\n
\n
\n

Defining Default parameters

\n

If we usually want a function to work one way, but occasionally need it to do something else, we can allow people to pass a parameter when they need to but provide a default to make the normal case easier. The example below shows how Python matches values to parameters:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-21", "source": [ "def display(a=1, b=2, c=3):\n", " print(f'a: {a}, b: {b}, c: {c}')\n", "\n", "# no parameters:\n", "display()\n", "# one parameter:\n", "display(55)\n", "# two parameters:\n", "display(55, 66)" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-22", "source": "

As this example shows, parameters are matched up from left to right, and any that haven’t been given a value explicitly get their default value. We can override this behavior by naming the value as we pass it in:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-23", "source": [ "# only setting the value of c\n", "display(c=77)" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-24", "source": "
\n

❓ Exercise: Signing a message

\n

Let’s test out a default argument. Imagine you are printing out a message, and at the bottom it should have a signature.

\n

Inputs:

\n\n

You can accomplish this with three print statements:

\n
    \n
  1. Print the message
  2. \n
  3. Print nothing (i.e. print())
  4. \n
  5. Print a signature variable.
  6. \n
\n
\n
Hint: Select the text with your mouse to see the answer

👁 Solution

\n
def myFunction(message, signature=\"Your name\"):\n    print(message)\n    print()\n    print(signature)\n
\n
\n
\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-25", "source": [ "# Test things out here!\n", "def myFunction # Fix this function!\n", "\n", "\n", "# Here are some test cases, for you to check if your function works!\n", "myFunction('This is a message')\n", "myFunction('This is a message', signature='Jane Doe')" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-26", "source": "\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "cell_type": "markdown", "id": "final-ending-cell", "metadata": { "editable": false, "collapsed": false }, "source": [ "# Key Points\n\n", "- Functions are foundational in Python\n", "- Everything you do will require functions\n", "\n# Congratulations on successfully completing this tutorial!\n\n", "Please [fill out the feedback on the GTN website](https://training.galaxyproject.org/training-material/topics/data-science/tutorials/python-functions/tutorial.html#feedback) and check there for further resources!\n" ] } ] }