{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Functional Programming in Python "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting toolz\n",
" Downloading toolz-0.7.4.tar.gz\n",
"Building wheels for collected packages: toolz\n",
" Running setup.py bdist_wheel for toolz ... \u001b[?25l-\b \b\\\b \bdone\n",
"\u001b[?25h Stored in directory: /home/jovyan/.cache/pip/wheels/3e/e9/72/b9e24c6b4c0347670b9a20afeba6b2534655f5dc714b30cb4e\n",
"Successfully built toolz\n",
"Installing collected packages: toolz\n",
"Successfully installed toolz-0.7.4\n",
"\u001b[33mYou are using pip version 8.1.1, however version 8.1.2 is available.\n",
"You should consider upgrading via the 'pip install --upgrade pip' command.\u001b[0m\n"
]
}
],
"source": [
"!pip install toolz"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import toolz\n",
"import operator\n",
"from operator import methodcaller, itemgetter, attrgetter"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Purity "
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# pure\n",
"def add(a, b):\n",
" return a + b\n",
"\n",
"# impure\n",
"additions_made = 0\n",
"def add(a, b):\n",
" global additions_made\n",
" additions_made += 1\n",
" return a + b\n",
"\n",
"add(3, 5)\n",
"add(6, 8)\n",
"additions_made"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## First class functions"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def add(a, b):\n",
" return a + b\n",
"\n",
"add_function = add\n",
" \n",
"add = lambda a,b: a + b\n",
"\n",
"add(1,1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Higher order functions"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"took 1.002180814743042\n"
]
}
],
"source": [
"from time import time, sleep\n",
"\n",
"def timer(fn):\n",
" def timed(*args, **kwargs):\n",
" t = time()\n",
" fn(*args, **kwargs)\n",
" print(\"took {time}\".format(time=time()-t))\n",
"\n",
" return timed\n",
"\n",
"def compute():\n",
" sleep(1)\n",
"\n",
"timed_compute = timer(compute)\n",
"timed_compute()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Decorators"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"took 1.0032811164855957\n"
]
}
],
"source": [
"@timer\n",
"def compute():\n",
" sleep(1)\n",
" \n",
"compute()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Partial function application "
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def add1(num):\n",
" return add(1, num)\n",
"add1(1)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from functools import partial\n",
"add1 = partial(add, 1)\n",
"add1(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Currying"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def curried_add(a):\n",
" def inner(b):\n",
" return add(a,b)\n",
" return inner\n",
"\n",
"curried_add(1)\n",
"curried_add(1)(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Function composition "
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[0, 4, 16, 36, 64]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from toolz.curried import compose, map, filter, pipe, curry\n",
"\n",
"compute = compose(map(lambda x: x**2), filter(lambda x: x%2==0))\n",
"\n",
"list(compute(range(10)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Example: Simplified CSV parsing"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"csv = \"\"\"firstName;lastName\n",
"Jim;Drake\n",
"Ben;James\n",
"Tim;Banes\"\"\""
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[{'firstName': 'Jim', 'lastName': 'Drake'},\n",
" {'firstName': 'Ben', 'lastName': 'James'},\n",
" {'firstName': 'Tim', 'lastName': 'Banes'}]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lines = csv.split(\"\\n\")\n",
"matrix = [line.split(';') for line in lines]\n",
"header = matrix.pop(0)\n",
"records = []\n",
"for row in matrix:\n",
" record = {}\n",
" for index, key in enumerate(header):\n",
" record[key] = row[index]\n",
" records.append(record)\n",
"records"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[{'firstName': 'Jim', 'lastName': 'Drake'},\n",
" {'firstName': 'Ben', 'lastName': 'James'},\n",
" {'firstName': 'Tim', 'lastName': 'Banes'}]"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from toolz.curried import compose, map\n",
"from functools import partial\n",
"from operator import methodcaller\n",
"\n",
"split = partial(methodcaller, 'split')\n",
"split_lines = split(\"\\n\")\n",
"split_fields = split(';')\n",
"dict_from_keys_vals = compose(dict, zip)\n",
"csv_to_matrix = compose(map(split_fields), split_lines)\n",
"\n",
"matrix = csv_to_matrix(csv)\n",
"keys = next(matrix)\n",
"records = map(partial(dict_from_keys_vals, keys), matrix)\n",
"list(records)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['foo', 'bar']"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from operator import methodcaller\n",
"methodcaller('split', ';')('foo;bar')"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[('a', 1), ('b', 2)]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(zip(['a','b'], [1,2]))"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"functools.partial(