Created
February 19, 2023 14:11
-
-
Save eriknw/adc62045e57435736d81646a3c6f499f to your computer and use it in GitHub Desktop.
Functional Programming Lightning Talk (blocksum example)
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", | |
"id": "76d38692-684f-4079-a3a9-95c08d5458ae", | |
"metadata": {}, | |
"source": [ | |
"# Functional Programming in Python by Example\n", | |
"## Me: Erik Welch (https://github.com/eriknw)\n", | |
"### maintainer of `toolz` and `cytoolz` functional programming packages (~10 years)\n", | |
"- `toolz` is the #222 most popular package on PyPI in the last month\n", | |
"- About 16_500_000 downloads from PyPI in the last month" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"id": "f07456d0-262b-4592-89d9-4192c36141ac", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"import random\n", | |
"import numpy as np\n", | |
"from pprint import pprint\n", | |
"\n", | |
"def show(list_of_lists):\n", | |
" pprint(list(list(row) for row in list_of_lists), width=20)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"id": "f191a52e-9c31-45e2-8f1b-607cb7fbb85f", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"data = [\n", | |
" [2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3],\n", | |
"]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "ea5969b2-3a49-4b6c-8ab3-db94e876fe17", | |
"metadata": {}, | |
"source": [ | |
"**input**: list of list of numbers\n", | |
"\n", | |
"**output**: list of list of numbers (same shape as input) \n", | |
"- `output[i][j]` = sum of all `inputs[ii][jj]` where `ii <= i` and `jj <= j`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"id": "3eb0d0d8-303d-400f-92a9-c337a47956a2", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def simple(data):\n", | |
" rv = [[0] * len(row) for row in data]\n", | |
" for i, row in enumerate(data):\n", | |
" for j, val in enumerate(row):\n", | |
" for ii in range(i + 1):\n", | |
" for jj in range(j + 1):\n", | |
" rv[i][j] = rv[i][j] + data[ii][jj]\n", | |
" return rv" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"id": "9c43e8a2-fdc4-4f94-857b-c9df61c48238", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"->\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print('->')\n", | |
"show(simple(data))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"id": "edc8f664-387f-4289-b93b-d067c118f31e", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[1, 1, 1],\n", | |
" [1, 1, 1],\n", | |
" [1, 1, 1]]\n", | |
"->\n", | |
"[[1, 2, 3],\n", | |
" [2, 4, 6],\n", | |
" [3, 6, 9]]\n" | |
] | |
} | |
], | |
"source": [ | |
"ones = [[1, 1, 1]] * 3\n", | |
"show(ones)\n", | |
"print('->')\n", | |
"show(simple(ones))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"id": "adc9c27d-fa2a-40ce-8e91-247b48c072c3", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"from itertools import accumulate as accum\n", | |
"from operator import add" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"id": "d24b79dd-122e-4fde-bde1-a1b6cabb18b0", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[1, 1, 1],\n", | |
" [1, 1, 1],\n", | |
" [1, 1, 1]]\n", | |
"-> cumsums ->\n", | |
"[[1, 2, 3],\n", | |
" [1, 2, 3],\n", | |
" [1, 2, 3]]\n" | |
] | |
} | |
], | |
"source": [ | |
"# cumsum for each row\n", | |
"show(ones)\n", | |
"print('-> cumsums ->')\n", | |
"show([\n", | |
" accum(row, add) for row in ones\n", | |
"])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"id": "ae70fc3c-54e7-4468-9e05-ab0fd3675ae0", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> transpose ->\n", | |
"[[2, 1, 9],\n", | |
" [4, 2, 2],\n", | |
" [3, 1, 3]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> transpose ->\")\n", | |
"show(zip(*data))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"id": "dfa62d6e-e488-43d8-ac8c-4d2dcfaad836", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[1, 1, 1],\n", | |
" [2, 2, 2],\n", | |
" [3, 3, 3]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(\n", | |
" zip(*(accum(row, add) for row in ones))\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"id": "61b80cc6-ee62-4ba3-bd1b-750527362cf1", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[1, 2, 3],\n", | |
" [2, 4, 6],\n", | |
" [3, 6, 9]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show([\n", | |
" accum(col, add)\n", | |
" for col in zip(*(accum(row, add) for row in ones))\n", | |
"])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"id": "0dc1b1ee-4a51-4a6b-8e41-eaa69ad908b9", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums ->\n", | |
"[[2, 3, 12],\n", | |
" [6, 9, 20],\n", | |
" [9, 13, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums ->\")\n", | |
"show([\n", | |
" accum(col, add)\n", | |
" for col in zip(*(accum(row, add) for row in data))\n", | |
"])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"id": "574a4139-7cd6-487b-9583-0742f84bb0c1", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" zip(*(\n", | |
" accum(col, add) for col in zip(*(\n", | |
" accum(row, add) for row in data\n", | |
" ))\n", | |
" ))\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"id": "6faf0795-f2ca-4288-b129-6cb23c8d5327", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def cumsum(seq):\n", | |
" prev = 0\n", | |
" return [prev := x + prev for x in seq]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"id": "5d3d0688-d0c6-4db8-a1c5-4eb78e557baa", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" zip(*(\n", | |
" cumsum(col) for col in zip(*(\n", | |
" cumsum(row) for row in data\n", | |
" ))\n", | |
" ))\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"id": "1a912828-2772-41d5-8b9e-3db8f492f001", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def transpose(seq):\n", | |
" return zip(*seq)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"id": "89332d21-f38f-4739-8c76-d4e8bbb6f331", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" transpose(\n", | |
" cumsum(col) for col in transpose(\n", | |
" cumsum(row) for row in data\n", | |
" )\n", | |
" )\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"id": "c75ac688-0d9e-4624-8c91-66165bac3323", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" transpose(cumsum(col) for col in transpose(cumsum(row) for row in data))\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"id": "70c68923-355c-4c80-aedb-19f1a269bf58", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" transpose(map(cumsum, transpose(map(cumsum, data))))\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"id": "81428447-dc57-4e0f-9500-7f595dc798b0", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def cumsums(data):\n", | |
" return map(cumsum, data)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"id": "1ff13e4a-f013-4380-95eb-fb170e16990b", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" transpose(cumsums(transpose(cumsums(data))))\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"id": "108f36a4-94c2-4e8c-896d-0b8ce856032f", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def pipe(data, *funcs):\n", | |
" for func in funcs:\n", | |
" data = func(data)\n", | |
" return data" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"id": "25ec6d66-5708-499d-9c6c-fcb3d52e2533", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" pipe(data, cumsums, transpose, cumsums, transpose)\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"id": "90d101b4-5391-4daa-b092-8e885f64abab", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def cmap(func):\n", | |
" def curried_map(seq):\n", | |
" return map(func, seq)\n", | |
" return curried_map" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"id": "c45170e3-48f8-43e5-80c3-e61958a2350a", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" pipe(data, cmap(cumsum), transpose, cmap(cumsum), transpose)\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"id": "032412ea-f6e4-4186-bf00-534973d74ea4", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"\u001b[0;31mInit signature:\u001b[0m \u001b[0maccum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitial\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mDocstring:\u001b[0m Return series of accumulated sums (or other binary function results).\n", | |
"\u001b[0;31mType:\u001b[0m type\n", | |
"\u001b[0;31mSubclasses:\u001b[0m " | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"accum?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"id": "545cc4e6-d3c9-4f38-af78-2a3816e1ed0b", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 4, 3],\n", | |
" [1, 2, 1],\n", | |
" [9, 2, 3]]\n", | |
"-> cumsums -> transpose -> cumsums -> transpose\n", | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"show(data)\n", | |
"print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
"show(\n", | |
" pipe(data, cmap(accum), transpose, cmap(accum), transpose)\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"id": "37eca2f4-1390-45d9-a6b2-f4c87271286e", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def blocksum(data):\n", | |
" return pipe(data, cmap(accum), transpose, cmap(accum), transpose, list)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"id": "5db396bc-1915-43bb-b361-bd0d8bcd983c", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def blocksum_alt1(data):\n", | |
" return pipe(data, cmap(cumsum), transpose, cmap(cumsum), transpose, list)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"id": "14c08873-d036-4a67-8062-d13bb29f83cd", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def blocksum_alt2(data):\n", | |
" return list(zip(*(\n", | |
" accum(col) for col in zip(*(\n", | |
" accum(row) for row in data\n", | |
" ))\n", | |
" )))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"id": "c5bb4f2f-5602-4400-9d29-cb3134deb350", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def blocksum_numpy(data):\n", | |
" # Convert input to NumPy array and convert result to Python list\n", | |
" return np.array(data).cumsum(axis=0).cumsum(axis=1).tolist()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"id": "ba5ceeff-56a4-4ec0-9619-3ff3d3de5014", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"def blocksum_proc(data):\n", | |
" # Optimized version of procedural style\n", | |
" rv = []\n", | |
" prevrow = [0] * len(data)\n", | |
" for row in data:\n", | |
" cur = []\n", | |
" left = 0\n", | |
" for val, above in zip(row, prevrow):\n", | |
" left += val + above\n", | |
" cur.append(left)\n", | |
" prevrow = row\n", | |
" rv.append(cur)\n", | |
" return rv" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "4dbd6d4e-5a44-47a5-b7d6-5dceab4d31b8", | |
"metadata": {}, | |
"source": [ | |
"## Benchmarks" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"id": "e5f2be73-72ee-4acd-bb74-6a39d5ed23f4", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"bigshape = (200, 200)\n", | |
"bigdata = [[random.randint(1, 9) for _ in range(bigshape[1])] for _ in range(bigshape[0])]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"id": "9e71cf47-b7d8-4f5f-8a07-c17166b64290", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"1.77 ms ± 121 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum(bigdata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"id": "b6230c4a-7db4-4d97-bad5-4b0067ce53f2", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"2.84 ms ± 76.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum_alt1(bigdata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"id": "591a7318-cbd0-49c9-800c-11a98ab8a1de", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"1.78 ms ± 46.5 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum_alt2(bigdata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"id": "0bea8d9d-7617-4ecc-b24a-eec708857c3b", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"2.11 ms ± 66.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum_numpy(bigdata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"id": "c86fb452-d08a-4a66-96f1-5fecadc7b7f6", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"2.47 ms ± 173 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum_proc(bigdata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"id": "7682e133-471b-452d-9f59-3ca714d5f39d", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"CPU times: user 25.9 s, sys: 0 ns, total: 25.9 s\n", | |
"Wall time: 25.9 s\n" | |
] | |
} | |
], | |
"source": [ | |
"%time _ = simple(bigdata) # more than 15_000 times slower!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "ffa80da2-1252-4243-bdd1-0af54a4c289b", | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"id": "5c890cb3-d5e1-4b25-a28c-80fa1a33b22e", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"hugeshape = (1000, 1000)\n", | |
"hugedata = [[random.randint(1, 9) for _ in range(hugeshape[1])] for _ in range(hugeshape[0])]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"id": "f3bbc1a3-498d-4d47-bbec-020f0554b740", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"71.6 ms ± 1.53 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum(hugedata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"id": "8675cd35-4232-4343-b45c-6d98de0b9f39", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"61.4 ms ± 628 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum_numpy(hugedata)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"id": "e07dbe48-c1d0-4716-8a3c-28c1a1e070cf", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"68.8 ms ± 2.93 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"%timeit blocksum_proc(hugedata)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "36027687-432a-4b3f-9173-cba5165a0625", | |
"metadata": {}, | |
"source": [ | |
"## `toolz` gives you the building blocks for writing clear functional-syle programming in Python\n", | |
"### and `cytoolz` is a faster version of `toolz` written in Cython\n", | |
"*Pro tip: use `tlz` to use the fastest version of `toolz` or `cytoolz` available*" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 43, | |
"id": "b4e532e2-7df1-432c-9255-a6e96d26908e", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"from tlz.curried import map, pipe, accumulate" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"id": "80afffd4-5b33-4e5a-bfaf-ebe94f034071", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[[2, 6, 9],\n", | |
" [3, 9, 13],\n", | |
" [12, 20, 27]]\n" | |
] | |
} | |
], | |
"source": [ | |
"pipe(\n", | |
" data,\n", | |
" map(accumulate(add)), # cumsum row-wise\n", | |
" transpose,\n", | |
" map(accumulate(add)), # cumsum column-wise\n", | |
" transpose,\n", | |
" show,\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "91215569-d0ca-4161-b9b2-d0c34c3391cb", | |
"metadata": {}, | |
"source": [ | |
"# Thank you!\n", | |
"## Me: Erik Welch (https://github.com/eriknw)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "0d979add-a5a8-48b0-ac9c-4b0e8ea047e4", | |
"metadata": {}, | |
"source": [ | |
"Bonus content--what is happening here?!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 45, | |
"id": "2b55eaa6-4e00-4c11-a693-bb2c59f89a3d", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"@(curry := lambda n, *a: lambda f: lambda *b: f(*c) if len(c := a + b) >= n else curry(n, *c)(f))(3)\n", | |
"def add3(*args):\n", | |
" assert len(args) >= 3\n", | |
" return sum(args)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 46, | |
"id": "437c4bcb-db9f-49f9-b974-e6fac4467919", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"6" | |
] | |
}, | |
"execution_count": 46, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"add3(1)(2)(3)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 47, | |
"id": "75d1cdd2-b739-47ce-ab9b-156e01b4317b", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"6" | |
] | |
}, | |
"execution_count": 47, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"add3(1, 2)()()(3)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 48, | |
"id": "f905cd7d-bd17-452e-8856-d7b55bcea986", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"6" | |
] | |
}, | |
"execution_count": 48, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"add3(1, 2, 3)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 49, | |
"id": "bb5c192e-ad54-4e3d-8c60-153d53e95818", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [], | |
"source": [ | |
"# This is equivalent to the above\n", | |
"def curry(n, *a):\n", | |
" def decorator(func):\n", | |
" def wrapper(*b):\n", | |
" c = a + b\n", | |
" if len(c) >= n:\n", | |
" return func(*c)\n", | |
" return curry(n, *c)(func)\n", | |
" return wrapper\n", | |
" return decorator\n", | |
"\n", | |
"\n", | |
"@curry(3)\n", | |
"def add3(*args):\n", | |
" assert len(args) >= 3\n", | |
" return sum(args)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 50, | |
"id": "9bf10183-556b-4001-8b30-d6907c8c4c10", | |
"metadata": { | |
"tags": [] | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 50, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"add3(1, 2)(3) == add3(1)(2)(3) == 6" | |
] | |
} | |
], | |
"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.10.9" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment