Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Functional Programming\n",
"\n",
"\n",
"Lesson Goals\n",
"\n",
" Learn the difference between procedural and functional programming style.\n",
" Learn about the components of functions and how to write them in Python.\n",
" Learn the difference between global and local variables and how they apply to functions.\n",
" Learn how to apply functions to Pandas data frames.\n",
"\n",
"\n",
"Introduction\n",
"\n",
"Up until this point, we have been writing Python code in a procedural manner and using functions and methods that are either in Python's standard library or part of some other library such as Numpy or Pandas. This has worked fine for us thus far, but in order to truly graduate from beginner to intermediate Python programmer, you must have a basic understanding of functional programming and be able to write your own functions.\n",
"\n",
"In this lesson, we will cover how to write Python code in a functional style and how to construct and call user-defined functions.\n",
"Procedural vs. Functional Programming\n",
"\n",
"Procedural code is code that is written line by line and executed in the order it is written. It is the style in which most people learn to program due to its straightforward sequence of actions to solve a problem - do this, then do this, then do this.\n",
"\n",
"More mature programmers frame problems a little differently. They take more of a functional approach to problem solving, where they create functions consisting of multiple lines of code that accomplish some task and often return a result that can be used by another function.\n",
"\n",
"You can think of a function as a tool - something that helps you perform a job. In a sense, functional programming allows you to create your own tools. Some of these tools will be designed specifically for the current set of tasks you need to perform while other functions you write will be more general and able to be used for other projects. Imagine if a chef were able to construct their own set of knives or a carpenter were able to construct their own set of saws that were perfect for the jobs they needed to perform. That is the power that functional programming gives you as a programmer. Over time, you will develop a personal library of functions that allow you to get your work done more efficiently.\n",
"\n",
"\n",
"Writing Functions in Python\n",
"\n",
"Functions in Python are defined by the def keyword followed by the function name and one or more inputs the function will need enclosed in parentheses. Within the function, you write code that performs the task you want the function to execute followed by a return statement if there is anything you would like the function to return. Below is an example of a list2string function that converts lists to strings. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'John was a man of many talents'"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def list2string(lst):\n",
" string = ' '.join(lst)\n",
" return string\n",
"\n",
"to_string = ['John', 'was', 'a', 'man', 'of', 'many', 'talents']\n",
"list2string(to_string)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example, we defined our list2string function and told it to expect one input. Within the function, we used the join method to convert the list to a string consisting of the list elements joined together by spaces. We then had the function return the string of space-separated elements.\n",
"\n",
"You can include all the concepts we have covered in past lessons (loops, conditional logic, list comprehensions, etc.) inside a function.\n",
"\n",
"\n",
"\n",
"\n",
"Global vs. Local Variables\n",
"\n",
"When writing functional code, it is important to keep track of which variables are global and which variables are local. Global variables are variables that maintain their value outside of functions. Local variables maintain their value within the function where they are defined and then cease to exist after we exit that function. In the example below, the variables a and c are global variables and variable b is a local variable that does not exist outside of the multiply function. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9 18\n"
]
}
],
"source": [
"a = 9\n",
"\n",
"def multiply(number, multiplier=2):\n",
" b = number * multiplier\n",
" return b\n",
"\n",
"c = multiply(a)\n",
"\n",
"print(a, c)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The multiply function above accepts a number and a multiplier (that defaults to 2), creates a local variable b that has a value of the number times the multiplier, and the function returns that value. We can see from the results of the example that global variable a (9) did get multiplied, returned, and assigned to another global variable c, so we know that b did exist within the function and was returned. However, now that the function has completed its job, we receive an error when we try to print b because it does not exist in the global variable namespace. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'b' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-3-67e500defa1b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mNameError\u001b[0m: name 'b' is not defined"
]
}
],
"source": [
"print(b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can enter any number into the function above and also override the default multiplier and our function will return the product of those two numbers."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"500"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"multiply(100, multiplier=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Applying Functions to Data Frames\n",
"\n",
"\n",
"Now that we have a basic understanding of how functions and variables work, let's look at how we can apply a function that we have created to a Pandas data frame. For this example, we will import Pandas and the vehicles data set we have been working with in this module. We will then write a get_means function that identifies all the numeric columns in the data set and returns a data frame containing each column name and its mean. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/iudh/.local/lib/python3.7/site-packages/IPython/core/interactiveshell.py:3044: DtypeWarning: Columns (70,71,72,73) have mixed types. Specify dtype option on import or set low_memory=False.\n",
" interactivity=interactivity, compiler=compiler, result=result)\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Column</th>\n",
" <th>Mean</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>barrels08</td>\n",
" <td>17.779002</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>barrelsA08</td>\n",
" <td>0.202128</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>charge120</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>charge240</td>\n",
" <td>0.009125</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>city08</td>\n",
" <td>17.574601</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Column Mean\n",
"0 barrels08 17.779002\n",
"1 barrelsA08 0.202128\n",
"2 charge120 0.000000\n",
"3 charge240 0.009125\n",
"4 city08 17.574601"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"\n",
"data = pd.read_csv('vehicles.csv')\n",
"\n",
"def get_means(df):\n",
" numeric = df._get_numeric_data()\n",
" means = pd.DataFrame(numeric.mean()).reset_index()\n",
" means.columns = ['Column', 'Mean']\n",
" return means\n",
"\n",
"mean_df = get_means(data)\n",
"mean_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we performed several steps with a single function call:\n",
"\n",
" Getting the numeric columns\n",
" Calculating the means\n",
" Resetting the indexes\n",
" Setting the data frame's column names\n",
"\n",
"Also note that the only input necessary for this function was a data frame. The function took care of everything else. That means that it should work for any data frame that you pass it, as long as the data frame has numeric columns. We have just created a tool by writing code once that we can use again and again.\n",
"\n",
"Challenge: Import another data set that contains numeric variables and run the get_means function on it. It should return the means for the numeric columns in that data set. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Loading