Last active
September 6, 2017 18:27
-
-
Save brianspiering/ae91413ab693bb066b483d330900d585 to your computer and use it in GitHub Desktop.
Closures for Data Science
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Closures for Data Science\n", | |
"------" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Problem\n", | |
"-----\n", | |
"\n", | |
"Sometimes you have data that is outside of valid bounds and has to be trimmed. If the data below a value, it should be changed to take the minimum value. If the data is above a value, it should be change to take on the maximum value.\n", | |
"\n", | |
"For example, RBG values can only be from 0 to 255:\n", | |
"\n", | |
"\n", | |
"\n", | |
"Here is a bound function:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def bound(value, min_value, max_value):\n", | |
" \"Limit value between the min and max\"\n", | |
" return min(max_value, max(value, min_value))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"assert bound(42, min_value=0, max_value=255) == 42\n", | |
"assert bound(-1, min_value=0, max_value=255) == 0\n", | |
"assert bound(256, min_value=0, max_value=255) == 255" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Python Function Superpower: <br> A Python function can return any object, including an another function!\n", | |
"--------\n", | |
"\n", | |
"Let's use that feature to create a variation of our bound function" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def make_bound_function(min_value, max_value):\n", | |
" \"Define a bound function with a certain min and max\"\n", | |
" def bound(value):\n", | |
" \"Limit value between the min and max\"\n", | |
" return min(max_value, max(value, min_value))\n", | |
" return bound" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Take moment to wrap your head around the idea that the outer function `make_bound_func` creates and returns the inner function `bound`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# Call the outer function to define/return the inner fuction\n", | |
"bound_rbg = make_bound_function(min_value=0, max_value=255)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"function" | |
] | |
}, | |
"execution_count": 32, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# The outer function returns the inner function\n", | |
"type(bound_rbg)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"42\n", | |
"0\n", | |
"255\n" | |
] | |
} | |
], | |
"source": [ | |
"# Call the inner function to bound the values\n", | |
"print(bound_rbg(42))\n", | |
"print(bound_rbg(-1))\n", | |
"print(bound_rbg(256))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This is a closure, a function wrapped in another function.\n", | |
"\n", | |
"The wrapping __binds__ the values/state to the inner function." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Another Problem\n", | |
"----\n", | |
"\n", | |
"Let's say our system can only take non-negative values.\n", | |
"\n", | |
"We can define another bound function that forces all negative numbers to be zero." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# Let's call the outer function again to define/return a different inner fuction\n", | |
"from math import inf\n", | |
"\n", | |
"bound_non_negative = make_bound_function(min_value=0, max_value=inf)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"42\n", | |
"0\n", | |
"1000000\n" | |
] | |
} | |
], | |
"source": [ | |
"# Call the inner function to bound the values\n", | |
"print(bound_non_negative(42))\n", | |
"print(bound_non_negative(-1))\n", | |
"print(bound_non_negative(1_000_000))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Summary\n", | |
"-----\n", | |
"\n", | |
"Closures are not required in Python. You can just pass a series of arguments to a function.\n", | |
"\n", | |
"Closures are a nice-to-have tool that can simplify complex function calls and create guard-rails for programming. Closures help build large, concurrent systems by \"freezing\" functions and limiting the dynamic nature of Python." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"<br>\n", | |
"<br> \n", | |
"<br>\n", | |
"\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.6.1" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment