Skip to content

Commit d737fb3

Browse files
committed
Improve formatting, add example using nonlocal, improve coroutine
1 parent 556cc6c commit d737fb3

File tree

1 file changed

+126
-45
lines changed

1 file changed

+126
-45
lines changed

source-code/functional-programming/functional_programming_style.ipynb

Lines changed: 126 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,25 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Functional programming style"
7+
"# Requirements"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": 5,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"from collections import Counter\n",
17+
"from functools import reduce, partial\n",
18+
"import random"
819
]
920
},
1021
{
1122
"cell_type": "markdown",
1223
"metadata": {},
1324
"source": [
14-
"## Applying function to iterables"
25+
"# Applying function to iterables"
1526
]
1627
},
1728
{
@@ -35,12 +46,18 @@
3546
}
3647
],
3748
"source": [
38-
"import random\n",
3949
"l1 = list(range(10))\n",
4050
"l2 = random.choices(range(3), k=7)\n",
4151
"print(l1, l2)"
4252
]
4353
},
54+
{
55+
"cell_type": "markdown",
56+
"metadata": {},
57+
"source": [
58+
"## map"
59+
]
60+
},
4461
{
4562
"cell_type": "markdown",
4663
"metadata": {},
@@ -84,6 +101,13 @@
84101
"Note that the result of `map` is not a list, but rather an iterator, even when it is appllied to a list."
85102
]
86103
},
104+
{
105+
"cell_type": "markdown",
106+
"metadata": {},
107+
"source": [
108+
"## filter"
109+
]
110+
},
87111
{
88112
"cell_type": "markdown",
89113
"metadata": {},
@@ -115,17 +139,14 @@
115139
"cell_type": "markdown",
116140
"metadata": {},
117141
"source": [
118-
"Python has quite number of reduction functions such as `sum`, `max`, and `min`, however, using the `reduce` function in `functools` we can easily write our own."
142+
"## reduce"
119143
]
120144
},
121145
{
122-
"cell_type": "code",
123-
"execution_count": 4,
146+
"cell_type": "markdown",
124147
"metadata": {},
125-
"outputs": [],
126148
"source": [
127-
"from collections import Counter\n",
128-
"from functools import reduce"
149+
"Python has quite number of reduction functions such as `sum`, `max`, and `min`, however, using the `reduce` function in `functools` we can easily write our own."
129150
]
130151
},
131152
{
@@ -208,7 +229,7 @@
208229
"cell_type": "markdown",
209230
"metadata": {},
210231
"source": [
211-
"## Higher order functions"
232+
"# Higher order functions"
212233
]
213234
},
214235
{
@@ -218,15 +239,6 @@
218239
"A new function can be created out of an existing function using `partial` to fix values for one or more arguments of the original function."
219240
]
220241
},
221-
{
222-
"cell_type": "code",
223-
"execution_count": 9,
224-
"metadata": {},
225-
"outputs": [],
226-
"source": [
227-
"from functools import partial"
228-
]
229-
},
230242
{
231243
"cell_type": "code",
232244
"execution_count": 10,
@@ -318,7 +330,70 @@
318330
"cell_type": "markdown",
319331
"metadata": {},
320332
"source": [
321-
"## Coroutines"
333+
"Closures can also be used to accumulate data. The following closure will generate a function that returns a value that is incremented by one on each invocation."
334+
]
335+
},
336+
{
337+
"cell_type": "code",
338+
"execution_count": 10,
339+
"metadata": {},
340+
"outputs": [],
341+
"source": [
342+
"def create_counter():\n",
343+
" n = 0\n",
344+
" def counter():\n",
345+
" nonlocal n\n",
346+
" n += 1\n",
347+
" return n\n",
348+
" return counter"
349+
]
350+
},
351+
{
352+
"cell_type": "code",
353+
"execution_count": 11,
354+
"metadata": {},
355+
"outputs": [],
356+
"source": [
357+
"c1, c2 = create_counter(), create_counter()"
358+
]
359+
},
360+
{
361+
"cell_type": "code",
362+
"execution_count": 12,
363+
"metadata": {},
364+
"outputs": [
365+
{
366+
"name": "stdout",
367+
"output_type": "stream",
368+
"text": [
369+
"1\n",
370+
"2\n",
371+
"3\n",
372+
"4 1\n",
373+
"5 2\n",
374+
"6 3\n"
375+
]
376+
}
377+
],
378+
"source": [
379+
"for _ in range(3):\n",
380+
" print(c1())\n",
381+
"for _ in range(3):\n",
382+
" print(c1(), c2())"
383+
]
384+
},
385+
{
386+
"cell_type": "markdown",
387+
"metadata": {},
388+
"source": [
389+
"`nonlocal` ensures that the `n` in outer scope is used, i.e., the variable `n` defined in the generating function `create_counter`."
390+
]
391+
},
392+
{
393+
"cell_type": "markdown",
394+
"metadata": {},
395+
"source": [
396+
"# Coroutines"
322397
]
323398
},
324399
{
@@ -337,59 +412,65 @@
337412
},
338413
{
339414
"cell_type": "code",
340-
"execution_count": 16,
415+
"execution_count": 24,
341416
"metadata": {},
342417
"outputs": [],
343418
"source": [
344419
"def create_elevator(highest_floor):\n",
345420
" def elevator():\n",
346-
" floor = 0\n",
421+
" prev_floor = None\n",
422+
" curr_floor = 0\n",
347423
" while True:\n",
348-
" next_floor = (yield f'current floor: {floor}')\n",
424+
" next_floor = (yield f'current floor: {curr_floor}' if prev_floor is None else f'move from {prev_floor} to {curr_floor}')\n",
349425
" if next_floor is not None:\n",
350-
" if 0 <= next_floor <= highest_floor:\n",
351-
" floor = next_floor\n",
426+
" if -1 <= next_floor <= highest_floor:\n",
427+
" prev_floor = curr_floor\n",
428+
" curr_floor = next_floor\n",
352429
" else:\n",
353430
" print(f'no such floor: {next_floor}')\n",
354431
" else:\n",
355432
" break\n",
356433
" my_elevator = elevator()\n",
357-
" next(my_elevator)\n",
434+
" print(next(my_elevator))\n",
358435
" return my_elevator "
359436
]
360437
},
361438
{
362439
"cell_type": "code",
363-
"execution_count": 17,
440+
"execution_count": 25,
364441
"metadata": {},
365-
"outputs": [],
442+
"outputs": [
443+
{
444+
"name": "stdout",
445+
"output_type": "stream",
446+
"text": [
447+
"current floor: 0\n"
448+
]
449+
}
450+
],
366451
"source": [
367-
"my_elevator = create_elevator(2)"
452+
"my_elevator = create_elevator(3)"
368453
]
369454
},
370455
{
371456
"cell_type": "code",
372-
"execution_count": 18,
457+
"execution_count": 26,
373458
"metadata": {},
374459
"outputs": [
375460
{
376461
"name": "stdout",
377462
"output_type": "stream",
378463
"text": [
379-
"no such floor: -1\n",
380-
"press -1: current floor: 0\n",
381-
"press 1: current floor: 1\n",
382-
"press 2: current floor: 2\n",
383-
"no such floor: 3\n",
384-
"press 3: current floor: 2\n",
385-
"press 2: current floor: 2\n",
386-
"press 0: current floor: 0\n",
387-
"no such floor: 3\n",
388-
"press 3: current floor: 0\n",
389-
"press 1: current floor: 1\n",
390-
"press 1: current floor: 1\n",
391-
"no such floor: -1\n",
392-
"press -1: current floor: 1\n"
464+
"press 0: move from 0 to 0\n",
465+
"press -1: move from 0 to -1\n",
466+
"press 1: move from -1 to 1\n",
467+
"press 3: move from 1 to 3\n",
468+
"press 3: move from 3 to 3\n",
469+
"press 1: move from 3 to 1\n",
470+
"press 0: move from 1 to 0\n",
471+
"press 3: move from 0 to 3\n",
472+
"press -1: move from 3 to -1\n",
473+
"press 0: move from -1 to 0\n"
393474
]
394475
}
395476
],
@@ -415,7 +496,7 @@
415496
"name": "python",
416497
"nbconvert_exporter": "python",
417498
"pygments_lexer": "ipython3",
418-
"version": "3.7.5"
499+
"version": "3.9.5"
419500
}
420501
},
421502
"nbformat": 4,

0 commit comments

Comments
 (0)