summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--notebooks/python/python_3_8_to_3_11.ipynb2
-rw-r--r--notebooks/python/python_intro.ipynb453
-rw-r--r--notebooks/python/python_oo.ipynb77
-rw-r--r--notebooks/sqlalchemy/sqlalchemy.ipynb6
4 files changed, 456 insertions, 82 deletions
diff --git a/notebooks/python/python_3_8_to_3_11.ipynb b/notebooks/python/python_3_8_to_3_11.ipynb
index fd5a3fc..1b0467c 100644
--- a/notebooks/python/python_3_8_to_3_11.ipynb
+++ b/notebooks/python/python_3_8_to_3_11.ipynb
@@ -834,7 +834,7 @@
834 "name": "python", 834 "name": "python",
835 "nbconvert_exporter": "python", 835 "nbconvert_exporter": "python",
836 "pygments_lexer": "ipython3", 836 "pygments_lexer": "ipython3",
837 "version": "3.11.0" 837 "version": "3.10.8"
838 } 838 }
839 }, 839 },
840 "nbformat": 4, 840 "nbformat": 4,
diff --git a/notebooks/python/python_intro.ipynb b/notebooks/python/python_intro.ipynb
index a2acfbc..3c49a14 100644
--- a/notebooks/python/python_intro.ipynb
+++ b/notebooks/python/python_intro.ipynb
@@ -62,7 +62,7 @@
62 }, 62 },
63 { 63 {
64 "cell_type": "code", 64 "cell_type": "code",
65 "execution_count": 96, 65 "execution_count": 50,
66 "id": "54c9e132-30b0-41bf-97e9-0e8b94f3d202", 66 "id": "54c9e132-30b0-41bf-97e9-0e8b94f3d202",
67 "metadata": {}, 67 "metadata": {},
68 "outputs": [], 68 "outputs": [],
@@ -109,7 +109,7 @@
109 }, 109 },
110 { 110 {
111 "cell_type": "code", 111 "cell_type": "code",
112 "execution_count": 97, 112 "execution_count": 51,
113 "id": "bd6134d9-cc0e-4b45-b6b3-50210f6395e2", 113 "id": "bd6134d9-cc0e-4b45-b6b3-50210f6395e2",
114 "metadata": {}, 114 "metadata": {},
115 "outputs": [], 115 "outputs": [],
@@ -122,7 +122,8 @@
122 "\n", 122 "\n",
123 "i = 6 # int, same as int('6'), immutable\n", 123 "i = 6 # int, same as int('6'), immutable\n",
124 "\n", 124 "\n",
125 "f = 0.1 # float, same as float('0.1'), immutable\n", 125 "f = 0.1 # float, same as float('0.1'), immutable, Note!!: Floats have a fixed size,\n",
126 "# hence they don't necessarily behave they way we expect from math class.\n",
126 "\n", 127 "\n",
127 "b = False # bool, same as bool(0), bool(''), bool(None)... immutable / constant\n", 128 "b = False # bool, same as bool(0), bool(''), bool(None)... immutable / constant\n",
128 "\n", 129 "\n",
@@ -138,6 +139,205 @@
138 ] 139 ]
139 }, 140 },
140 { 141 {
142 "cell_type": "code",
143 "execution_count": 52,
144 "id": "cd2b7f98-ea16-49e2-9d19-f37266bd4f3a",
145 "metadata": {},
146 "outputs": [
147 {
148 "name": "stdout",
149 "output_type": "stream",
150 "text": [
151 "'can be written like this'\n"
152 ]
153 },
154 {
155 "data": {
156 "text/plain": [
157 "'foo bar'"
158 ]
159 },
160 "execution_count": 52,
161 "metadata": {},
162 "output_type": "execute_result"
163 },
164 {
165 "name": "stdout",
166 "output_type": "stream",
167 "text": [
168 "works just fine\n",
169 "works\n",
170 "just\n",
171 "fine\n"
172 ]
173 },
174 {
175 "data": {
176 "text/plain": [
177 "'S'"
178 ]
179 },
180 "execution_count": 52,
181 "metadata": {},
182 "output_type": "execute_result"
183 },
184 {
185 "data": {
186 "text/plain": [
187 "'t'"
188 ]
189 },
190 "execution_count": 52,
191 "metadata": {},
192 "output_type": "execute_result"
193 },
194 {
195 "data": {
196 "text/plain": [
197 "'tatnett'"
198 ]
199 },
200 "execution_count": 52,
201 "metadata": {},
202 "output_type": "execute_result"
203 },
204 {
205 "data": {
206 "text/plain": [
207 "'tatnet'"
208 ]
209 },
210 "execution_count": 52,
211 "metadata": {},
212 "output_type": "execute_result"
213 },
214 {
215 "data": {
216 "text/plain": [
217 "'ett'"
218 ]
219 },
220 "execution_count": 52,
221 "metadata": {},
222 "output_type": "execute_result"
223 },
224 {
225 "data": {
226 "text/plain": [
227 "'tte'"
228 ]
229 },
230 "execution_count": 52,
231 "metadata": {},
232 "output_type": "execute_result"
233 },
234 {
235 "data": {
236 "text/plain": [
237 "True"
238 ]
239 },
240 "execution_count": 52,
241 "metadata": {},
242 "output_type": "execute_result"
243 },
244 {
245 "data": {
246 "text/plain": [
247 "False"
248 ]
249 },
250 "execution_count": 52,
251 "metadata": {},
252 "output_type": "execute_result"
253 },
254 {
255 "data": {
256 "text/plain": [
257 "True"
258 ]
259 },
260 "execution_count": 52,
261 "metadata": {},
262 "output_type": "execute_result"
263 },
264 {
265 "data": {
266 "text/plain": [
267 "b'B\\xc3\\x98!'"
268 ]
269 },
270 "execution_count": 52,
271 "metadata": {},
272 "output_type": "execute_result"
273 },
274 {
275 "data": {
276 "text/plain": [
277 "'BØ!'"
278 ]
279 },
280 "execution_count": 52,
281 "metadata": {},
282 "output_type": "execute_result"
283 }
284 ],
285 "source": [
286 "# Strings and bytes\n",
287 "\n",
288 "# apart from other programming languages (PHP, Perl), the next two lines are virtually equal in Python\n",
289 "s = 'can be written like this' # ... and should be written like this\n",
290 "s = \"can be written like this\"\n",
291 "print(repr(s)) # the official Python repr uses single quotes\n",
292 "\n",
293 "# the only important difference:\n",
294 "s = 'can\\'t be written like this'\n",
295 "s = \"can't be written like this\" # better\n",
296 "s = \"can be written \\\"like this\\\"\"\n",
297 "s = 'can be written \"like this\"' # better\n",
298 "\n",
299 "s1 = 'foo'\n",
300 "s2 = 'bar'\n",
301 "s1 + ' ' + s2\n",
302 "\n",
303 "# without new line\n",
304 "print(\n",
305 " 'works '\n",
306 " 'just '\n",
307 " 'fine'\n",
308 ")\n",
309 "\n",
310 "# with new line\n",
311 "print(\n",
312 " 'works\\n'\n",
313 " 'just\\n'\n",
314 " 'fine'\n",
315 ")\n",
316 "\n",
317 "# slicing [from:until(not included):step] - produces a new string (copy)\n",
318 "s3 = 'Statnett'\n",
319 "s3[0] # Out: S\n",
320 "s3[-1] # Out: t\n",
321 "s3[1:] # Out: tatnett\n",
322 "s3[1:-1] # Out: tatnett\n",
323 "s3[-3:] # Out: ett\n",
324 "s3[1:-1:2] # Out: tte\n",
325 "\n",
326 "s3.endswith('nett') # Out: True\n",
327 "s3.startswith('sta') # Out: False (case sensitive)\n",
328 "s3[-4:] == 'nett' # works, but BAD coding style\n",
329 "\n",
330 "# All strings in Python 3 are unicode strings (unicode type) and not byte strings as in Python 2\n",
331 "# One doesn't write strings to: files, sockets, cryptographic functions etc... but rather 'bytes'\n",
332 "\n",
333 "# from unicode string to bytes (UTF-8)\n",
334 "'BØ!'.encode('utf-8') # utf-8 is implicit in Python 3\n",
335 "\n",
336 "# bytes to unicode\n",
337 "b'B\\xc3\\x98!'.decode('utf-8') # utf-8 is implicit in Python 3"
338 ]
339 },
340 {
141 "cell_type": "markdown", 341 "cell_type": "markdown",
142 "id": "6b2bc8fa-a5dc-4a58-92b2-abfb19bfe2ed", 342 "id": "6b2bc8fa-a5dc-4a58-92b2-abfb19bfe2ed",
143 "metadata": {}, 343 "metadata": {},
@@ -320,27 +520,27 @@
320 }, 520 },
321 { 521 {
322 "cell_type": "code", 522 "cell_type": "code",
323 "execution_count": 98, 523 "execution_count": 53,
324 "id": "f4a4ea99-4038-4b61-9b8d-9ce623e6a663", 524 "id": "f4a4ea99-4038-4b61-9b8d-9ce623e6a663",
325 "metadata": {}, 525 "metadata": {},
326 "outputs": [ 526 "outputs": [
327 { 527 {
328 "data": { 528 "data": {
329 "text/plain": [ 529 "text/plain": [
330 "35041378544" 530 "35082617072"
331 ] 531 ]
332 }, 532 },
333 "execution_count": 98, 533 "execution_count": 53,
334 "metadata": {}, 534 "metadata": {},
335 "output_type": "execute_result" 535 "output_type": "execute_result"
336 }, 536 },
337 { 537 {
338 "data": { 538 "data": {
339 "text/plain": [ 539 "text/plain": [
340 "35041378576" 540 "35082617104"
341 ] 541 ]
342 }, 542 },
343 "execution_count": 98, 543 "execution_count": 53,
344 "metadata": {}, 544 "metadata": {},
345 "output_type": "execute_result" 545 "output_type": "execute_result"
346 }, 546 },
@@ -350,7 +550,7 @@
350 "'H'" 550 "'H'"
351 ] 551 ]
352 }, 552 },
353 "execution_count": 98, 553 "execution_count": 53,
354 "metadata": {}, 554 "metadata": {},
355 "output_type": "execute_result" 555 "output_type": "execute_result"
356 }, 556 },
@@ -360,47 +560,47 @@
360 "-6333845781340707986" 560 "-6333845781340707986"
361 ] 561 ]
362 }, 562 },
363 "execution_count": 98, 563 "execution_count": 53,
364 "metadata": {}, 564 "metadata": {},
365 "output_type": "execute_result" 565 "output_type": "execute_result"
366 }, 566 },
367 { 567 {
368 "data": { 568 "data": {
369 "text/plain": [ 569 "text/plain": [
370 "36321214208" 570 "36350585520"
371 ] 571 ]
372 }, 572 },
373 "execution_count": 98, 573 "execution_count": 53,
374 "metadata": {}, 574 "metadata": {},
375 "output_type": "execute_result" 575 "output_type": "execute_result"
376 }, 576 },
377 { 577 {
378 "data": { 578 "data": {
379 "text/plain": [ 579 "text/plain": [
380 "36321613808" 580 "36350587520"
381 ] 581 ]
382 }, 582 },
383 "execution_count": 98, 583 "execution_count": 53,
384 "metadata": {}, 584 "metadata": {},
385 "output_type": "execute_result" 585 "output_type": "execute_result"
386 }, 586 },
387 { 587 {
388 "data": { 588 "data": {
389 "text/plain": [ 589 "text/plain": [
390 "27542959409390741" 590 "8927089887582119463"
391 ] 591 ]
392 }, 592 },
393 "execution_count": 98, 593 "execution_count": 53,
394 "metadata": {}, 594 "metadata": {},
395 "output_type": "execute_result" 595 "output_type": "execute_result"
396 }, 596 },
397 { 597 {
398 "data": { 598 "data": {
399 "text/plain": [ 599 "text/plain": [
400 "27542959409390741" 600 "8927089887582119463"
401 ] 601 ]
402 }, 602 },
403 "execution_count": 98, 603 "execution_count": 53,
404 "metadata": {}, 604 "metadata": {},
405 "output_type": "execute_result" 605 "output_type": "execute_result"
406 } 606 }
@@ -442,6 +642,9 @@
442 "\n", 642 "\n",
443 "A function is a sequence of program instructions that performs a specific task, packaged as a unit.\n", 643 "A function is a sequence of program instructions that performs a specific task, packaged as a unit.\n",
444 "\n", 644 "\n",
645 "\n",
646 "### Why use functions?\n",
647 "\n",
445 "Functions let you:\n", 648 "Functions let you:\n",
446 "\n", 649 "\n",
447 "- reuse code across several programs / projects\n", 650 "- reuse code across several programs / projects\n",
@@ -456,20 +659,51 @@
456 "\n", 659 "\n",
457 "- improve traceability\n", 660 "- improve traceability\n",
458 "\n", 661 "\n",
662 "\n",
663 "### Any downside?\n",
664 "\n",
459 "Function calls bring some overhead pushing / popping function-data into / from stack.\n", 665 "Function calls bring some overhead pushing / popping function-data into / from stack.\n",
460 "\n", 666 "\n",
667 "```python\n",
668 "empty_list = list()\n",
669 "empty_dict = dict()\n",
670 "\n",
671 "# better since it avoids the function call:\n",
672 "empty_list = []\n",
673 "empty_dict = {}\n",
674 "```\n",
675 "\n",
676 "\n",
677 "### Definitions\n",
678 "\n",
461 "Important definitions (may have different meanings in different programming languages):\n", 679 "Important definitions (may have different meanings in different programming languages):\n",
462 "\n", 680 "\n",
463 "- *parameter / formal parameter* - variable / data provided as input to the function\n", 681 "- *parameter / formal parameter* - the names that appear in a function definition. Parameters define what kind of arguments a function can accept.\n",
682 "\n",
683 "- *argument / actual parameter* - the values actually passed to a function when calling it.\n",
464 "\n", 684 "\n",
465 "- *argument / actual parameter* - local variable / data to the given function\n",
466 "\n", 685 "\n",
467 "The keyword `def` introduces a function definition." 686 "The keyword `def` introduces a function definition.\n",
687 "\n",
688 "Given the function definition:\n",
689 "\n",
690 "```python\n",
691 "def func(foo, bar=None, **kwargs):\n",
692 " pass\n",
693 "```\n",
694 "\n",
695 "`foo`, `bar` and `kwargs` are **parameters** of `func`. However, when calling func, for example:\n",
696 "\n",
697 "```python\n",
698 "func(42, bar=314, extra=somevar)\n",
699 "```\n",
700 "\n",
701 "the values `42`, `314`, and `somevar` are arguments."
468 ] 702 ]
469 }, 703 },
470 { 704 {
471 "cell_type": "code", 705 "cell_type": "code",
472 "execution_count": 99, 706 "execution_count": 54,
473 "id": "bf95f44a-1257-440f-b35f-a8536c8c4363", 707 "id": "bf95f44a-1257-440f-b35f-a8536c8c4363",
474 "metadata": {}, 708 "metadata": {},
475 "outputs": [ 709 "outputs": [
@@ -479,7 +713,7 @@
479 "7" 713 "7"
480 ] 714 ]
481 }, 715 },
482 "execution_count": 99, 716 "execution_count": 54,
483 "metadata": {}, 717 "metadata": {},
484 "output_type": "execute_result" 718 "output_type": "execute_result"
485 }, 719 },
@@ -496,7 +730,7 @@
496 "[9, -2]" 730 "[9, -2]"
497 ] 731 ]
498 }, 732 },
499 "execution_count": 99, 733 "execution_count": 54,
500 "metadata": {}, 734 "metadata": {},
501 "output_type": "execute_result" 735 "output_type": "execute_result"
502 }, 736 },
@@ -511,36 +745,47 @@
511 "source": [ 745 "source": [
512 "# Functions (example1)\n", 746 "# Functions (example1)\n",
513 "\n", 747 "\n",
748 "# case1: assuming that the arguments are of ummutable type (f.i. int):\n",
514 "def add(a, b): # - function definition / header\n", 749 "def add(a, b): # - function definition / header\n",
515 " \"\"\"Function for adding integers\"\"\" # - docstring\n", 750 " \"\"\"Function for adding two integers\"\"\" # - docstring\n",
751 " # the function body will not be evaluated (executed) before the function is called\n",
516 " result = a + b\n", 752 " result = a + b\n",
517 " a = 5 # will not change the corresponding parameter since it is immutable\n", 753 " a = 5 # will not change the corresponding argument since it is immutable\n",
518 " return result # - function that does not contain return, implicitly returns None\n", 754 " return result # - function that does not contain return, implicitly returns None\n",
519 "\n", 755 "\n",
520 "a_param = 9\n", 756 "# defining two integer variables to be used as arguments when calling the function `add`\n",
521 "b_param = -2\n", 757 "a_var = 9\n",
522 "add(a_param, b_param) # Out: 7\n", 758 "b_var = -2\n",
759 "\n",
760 "add(a_var, b_var) # Out: 7\n",
523 "\n", 761 "\n",
524 "# integers are immutable and a_param will remain unchanged\n", 762 "# even though a_var and a point at the same data (they are references: a = a_var),\n",
525 "print(a_param) # Out: 9\n", 763 "# integers are immutable and a_var will remain unchanged\n",
764 "print(a_var) # Out: 9\n",
526 "\n", 765 "\n",
527 "\n", 766 "\n",
767 "# case2: assuming that the arguments are of mutable type (f.i. list)\n",
528 "def addl(a, b):\n", 768 "def addl(a, b):\n",
529 " \"\"\"Function for adding two lists\"\"\"\n", 769 " \"\"\"Function for adding two lists\"\"\"\n",
530 " result = a + b\n", 770 " # assuming that a and b are lists\n",
531 " a += [5] # in this case equal to: a.append(5)\n", 771 " result = a + b # produces a new list that contains the elements of `a` followed by the elements of `b`\n",
772 " a.append(5) # appending a new int element - 5 to the list `a`\n",
532 " return result\n", 773 " return result\n",
533 "\n", 774 "\n",
534 "a_param = [9]\n", 775 "# defining two lists with one element each to be used as arguments when calling `addl`\n",
535 "b_param = [-2]\n", 776 "a_var = [9]\n",
536 "addl(a_param, b_param) # Out: [9, -2]\n", 777 "b_var = [-2]\n",
537 "# lists are mutable and a_param will be changed\n", 778 "\n",
538 "print(a_param) # Out: [9, 5]" 779 "addl(a_var, b_var) # Out: [9, -2]\n",
780 "\n",
781 "# since a (inside the function) is a reference of a_var (a = a_var) and\n",
782 "# lists are mutable and `a_var` will be changed inside the function\n",
783 "print(a_var) # Out: [9, 5]"
539 ] 784 ]
540 }, 785 },
541 { 786 {
542 "cell_type": "code", 787 "cell_type": "code",
543 "execution_count": 100, 788 "execution_count": 55,
544 "id": "ecd03ee2-3523-40bd-afd1-4263a777bae0", 789 "id": "ecd03ee2-3523-40bd-afd1-4263a777bae0",
545 "metadata": {}, 790 "metadata": {},
546 "outputs": [], 791 "outputs": [],
@@ -551,8 +796,15 @@
551 " \"\"\"Function for adding integers\"\"\"\n", 796 " \"\"\"Function for adding integers\"\"\"\n",
552 " return a + b\n", 797 " return a + b\n",
553 "\n", 798 "\n",
554 "my_result = add(2, 5) # positional arguments (parameters)\n", 799 "# positional arguments:\n",
555 "my_result = add(b=5, a=2) # keyword arguments (parameters)\n", 800 "# the order by which the arguments are sent to the function decides\n",
801 "# which argument is assigned to which parameter\n",
802 "my_result = add(2, 5)\n",
803 "\n",
804 "# keyword arguments:\n",
805 "# which argument is assigned to which parameter is decided by\n",
806 "# referrig directly to the argument names - keyword arguments (kwargs)\n",
807 "my_result = add(b=5, a=2)\n",
556 "\n", 808 "\n",
557 "my_tuple = (2, 5)\n", 809 "my_tuple = (2, 5)\n",
558 "my_dict = {'b': 5, 'a': 2}\n", 810 "my_dict = {'b': 5, 'a': 2}\n",
@@ -560,12 +812,15 @@
560 "my_result = add(*my_tuple) # unpacked and assigned to the positional arguments\n", 812 "my_result = add(*my_tuple) # unpacked and assigned to the positional arguments\n",
561 "my_result = add(**my_dict) # unpacked and assigned to the kw. arguments\n", 813 "my_result = add(**my_dict) # unpacked and assigned to the kw. arguments\n",
562 "\n", 814 "\n",
815 "# defining the function `add`with defaukt value for argument `b`\n",
563 "def add(a, b=5):\n", 816 "def add(a, b=5):\n",
564 " \"\"\"Function for adding integers\"\"\"\n", 817 " \"\"\"Function for adding integers\"\"\"\n",
565 " return a + b\n", 818 " return a + b\n",
566 "my_result = add(2)\n", 819 "my_result = add(2) # the default value for `b` is used unless a parameter is sent / used\n",
567 "# ... and the rest of the examples above will work\n",
568 "\n", 820 "\n",
821 "# assigning a varying amount of arguments to parameters\n",
822 "# # args - tuple containing all positional arguments (with the exception of `a`)\n",
823 "# kwargs - a {keyword: value} dict containing all keyword arguments\n",
569 "def add(a, *args, **kwargs):\n", 824 "def add(a, *args, **kwargs):\n",
570 " \"\"\"Function for adding integers\"\"\"\n", 825 " \"\"\"Function for adding integers\"\"\"\n",
571 " if args:\n", 826 " if args:\n",
@@ -575,12 +830,58 @@
575 " return a + b\n", 830 " return a + b\n",
576 "\n", 831 "\n",
577 "my_result = add(2, 5, 9, 11) # 5 assigned to args[0]\n", 832 "my_result = add(2, 5, 9, 11) # 5 assigned to args[0]\n",
578 "my_result = add(2, b=5, c=9, d=11) # 5 assigned to kwargs['b']\n", 833 "my_result = add(2, 6, 5, b=5, c=9, d=11) # 5 assigned to kwargs['b']\n",
579 "\n", 834 "\n",
580 "# my_result = add(2, b=5, 9, 11) # SyntaxError: positional argument follows keyword argument" 835 "# my_result = add(2, b=5, 9, 11) # SyntaxError: positional argument follows keyword argument"
581 ] 836 ]
582 }, 837 },
583 { 838 {
839 "cell_type": "code",
840 "execution_count": 56,
841 "id": "c67ca162-e8eb-4b4d-8c3c-246b000c5c13",
842 "metadata": {},
843 "outputs": [
844 {
845 "name": "stdout",
846 "output_type": "stream",
847 "text": [
848 "10 20 {'a': 1, 'b': 2, 'c': 3}\n"
849 ]
850 }
851 ],
852 "source": [
853 "# Positional only parameters:\n",
854 "# def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):\n",
855 "# ----------- ---------- ----------\n",
856 "# | | |\n",
857 "# | Positional or keyword |\n",
858 "# | - Keyword only\n",
859 "# -- Positional only\n",
860 "\n",
861 "# Positional-only parameters give more control to library authors to better\n",
862 "# express the intended usage of an API and allows the API to evolve in a safe, backward-compatible way.\n",
863 "# Additionally, it makes the Python language more consistent with existing documentation and\n",
864 "# the behavior of various “builtin” and standard library functions.\n",
865 "\n",
866 "# One use case for this notation is that it allows pure Python functions to fully emulate behaviors of existing C coded functions.\n",
867 "# For example, the built-in divmod() function does not accept keyword arguments:\n",
868 "def divmod(a, b, /):\n",
869 " \"\"\"Emulate the built in divmod() function\"\"\"\n",
870 " return (a // b, a % b)\n",
871 "\n",
872 "# Another use case is to preclude keyword arguments when the parameter name is not helpful.\n",
873 "# For example, the builtin len() function has the signature len(obj, /).\n",
874 "# This precludes awkward calls such as: len(obj='hello'), where the \"obj\" keyword argument impairs readability.\n",
875 "\n",
876 "# A further benefit of marking a parameter as positional-only is that it allows the parameter name to be changed in the future without risk of breaking client code.\n",
877 "\n",
878 "def my_func(a, b, /, **kwargs):\n",
879 " print(a, b, kwargs)\n",
880 "\n",
881 "my_func(10, 20, a=1, b=2, c=3)"
882 ]
883 },
884 {
584 "cell_type": "markdown", 885 "cell_type": "markdown",
585 "id": "26a4f2fe-b79e-4e25-9107-230a53d11373", 886 "id": "26a4f2fe-b79e-4e25-9107-230a53d11373",
586 "metadata": {}, 887 "metadata": {},
@@ -654,11 +955,15 @@
654 }, 955 },
655 { 956 {
656 "cell_type": "code", 957 "cell_type": "code",
657 "execution_count": 101, 958 "execution_count": 57,
658 "id": "edf9cfa7-d76c-428b-a39f-8c0697789031", 959 "id": "edf9cfa7-d76c-428b-a39f-8c0697789031",
659 "metadata": {}, 960 "metadata": {},
660 "outputs": [], 961 "outputs": [],
661 "source": [ 962 "source": [
963 "# example: function as a parameter / argument\n",
964 "# the built-in function map: map(function, iterable, *iterables)\n",
965 "\n",
966 "\n",
662 "def fetch_the_first_letter(input_str: str) -> str:\n", 967 "def fetch_the_first_letter(input_str: str) -> str:\n",
663 " \"\"\"Fetches the first letter of the string input_str or 'x'\"\"\"\n", 968 " \"\"\"Fetches the first letter of the string input_str or 'x'\"\"\"\n",
664 " try:\n", 969 " try:\n",
@@ -672,8 +977,8 @@
672 "letter_list = list(map(lambda x: x[0], ['foo', 'bar', 'test'])) # Out: ['f', 'b', 't']\n", 977 "letter_list = list(map(lambda x: x[0], ['foo', 'bar', 'test'])) # Out: ['f', 'b', 't']\n",
673 "\n", 978 "\n",
674 "\n", 979 "\n",
980 "# example: function returning multiple values\n",
675 "# A function can return multiple values by implicitly returning a tuple:\n", 981 "# A function can return multiple values by implicitly returning a tuple:\n",
676 "\n",
677 "def square_cube(x):\n", 982 "def square_cube(x):\n",
678 " \"\"\"returns x, x^2 and x^3\"\"\"\n", 983 " \"\"\"returns x, x^2 and x^3\"\"\"\n",
679 " return x, x**2, x**3\n", 984 " return x, x**2, x**3\n",
@@ -700,7 +1005,7 @@
700 }, 1005 },
701 { 1006 {
702 "cell_type": "code", 1007 "cell_type": "code",
703 "execution_count": 102, 1008 "execution_count": 58,
704 "id": "ea583c17-c938-495a-9586-2027c66328a2", 1009 "id": "ea583c17-c938-495a-9586-2027c66328a2",
705 "metadata": {}, 1010 "metadata": {},
706 "outputs": [ 1011 "outputs": [
@@ -715,9 +1020,17 @@
715 ], 1020 ],
716 "source": [ 1021 "source": [
717 "# enclosing functions\n", 1022 "# enclosing functions\n",
1023 "# used when:\n",
1024 "# - we want to dynamically generate a function\n",
1025 "# - we want to hide implementation details (encapsulation)\n",
1026 "\n",
1027 "# when we want to dynamically generate a function:\n",
1028 "# the function will behave differently depending on what parameters were\n",
1029 "# used when calling its enclosing function (factory function)\n",
718 "\n", 1030 "\n",
719 "def get_multiplier_of(base: int) -> str:\n", 1031 "def get_multiplier_of(base: int) -> str:\n",
720 " \"\"\"the function enclosing its nested functions\"\"\"\n", 1032 " \"\"\"the function enclosing its nested functions\"\"\"\n",
1033 " # this function is the enclosing function of the function `multiplier_function`\n",
721 "\n", 1034 "\n",
722 " def multiplier_function(x):\n", 1035 " def multiplier_function(x):\n",
723 " \"\"\"a nested function\"\"\"\n", 1036 " \"\"\"a nested function\"\"\"\n",
@@ -751,7 +1064,7 @@
751 }, 1064 },
752 { 1065 {
753 "cell_type": "code", 1066 "cell_type": "code",
754 "execution_count": 103, 1067 "execution_count": 59,
755 "id": "49d7f6e1-1f54-4b96-8203-5eae95f47ebe", 1068 "id": "49d7f6e1-1f54-4b96-8203-5eae95f47ebe",
756 "metadata": {}, 1069 "metadata": {},
757 "outputs": [ 1070 "outputs": [
@@ -761,36 +1074,49 @@
761 "text": [ 1074 "text": [
762 "7 8\n", 1075 "7 8\n",
763 "100\n", 1076 "100\n",
764 "{'num3': 100, 'id': 200}\n", 1077 "{'id': 200, 'num3': 100, 'num5': 23}\n",
765 "{}\n", 1078 "{'num3': 100, 'num5': 23}\n",
766 "{}\n", 1079 "100\n",
1080 "{'num3': 100, 'num5': 25}\n",
1081 "100\n",
1082 "25\n",
767 "99\n" 1083 "99\n"
768 ] 1084 ]
769 } 1085 }
770 ], 1086 ],
771 "source": [ 1087 "source": [
772 "num1, num2 = 7, 8 # module globals\n", 1088 "# module globals\n",
1089 "num1 = 7\n",
1090 "num2 = 8\n",
773 "\n", 1091 "\n",
774 "def print_numbers():\n", 1092 "def print_numbers():\n",
775 " print(num1, num2) # OK, these are module globals\n", 1093 " print(num1, num2) # module globals. Out: 7 8\n",
776 " num3 = 100\n", 1094 " num3 = 100\n",
777 " print(num3) # prints 100, num3 is in the function (local) scope\n", 1095 " print(num3) # prints 100, num3 is in the function (local) scope\n",
778 " global num4 # assignes / references num4 to / in the global scope\n", 1096 " global num4 # assignes / references num4 to / in the global scope\n",
779 " num4 = 99\n", 1097 " num4 = 99\n",
780 " id = 200 # new symbol in local scope\n", 1098 " id = 200 # new symbol in local scope\n",
781 " # id(num4) # will not yield the expected result (raises TypeError)\n", 1099 " # id(num4) # will not yield the expected result (raises TypeError)\n",
1100 " num5 = 23\n",
1101 " \n",
1102 " # locals() updates and then returns a dictionary representing the current local symbol table\n",
782 " print(locals())\n", 1103 " print(locals())\n",
783 "\n", 1104 "\n",
784 " def print_numbers2():\n", 1105 " def print_numbers2():\n",
785 " print(locals())\n", 1106 " print(locals()) # N.B. Updates and then displays the local symbol table (num3 will be included)\n",
786 " # print(num3) # OK, enclosed scope\n", 1107 " print(num3) # OK, enclosed scope\n",
1108 " # num3 = 9 # UnboundLocalError: local variable 'num3' referenced before assignment\n",
1109 " nonlocal num5 # assignes / references num5 to / in enclosing scope. N.B. num5 must exist in `print_numbers`\n",
1110 " num5 = 25\n",
787 " print(locals())\n", 1111 " print(locals())\n",
788 "\n", 1112 "\n",
789 " print_numbers2() # prints 100\n", 1113 " print_numbers2() # Out: 100\n",
1114 " print(num3)\n",
1115 " print(num5) # Out: 25\n",
790 "\n", 1116 "\n",
791 "print_numbers()\n", 1117 "print_numbers()\n",
792 "# print(num3) # Raises NameError - why?\n", 1118 "# print(num3) # Raises NameError - why?\n",
793 "print(num4) # Prints 99 - why?\n", 1119 "print(num4) # Out: 99\n",
794 "# print_numbers2() # Raises NameError" 1120 "# print_numbers2() # Raises NameError"
795 ] 1121 ]
796 }, 1122 },
@@ -807,12 +1133,18 @@
807 "def my_decorator(func):\n", 1133 "def my_decorator(func):\n",
808 "\n", 1134 "\n",
809 " def decorated():\n", 1135 " def decorated():\n",
1136 " # we place the logic we want to take place before the decorated function's logic here\n",
810 " print('Doing something before the decorated function')\n", 1137 " print('Doing something before the decorated function')\n",
811 " retval = func()\n", 1138 " retval = func() # calling the decorated function and (optionally) taking care of its return value\n",
1139 " # we place the logic we want to take place after the decorated function's logic here\n",
812 " print('Doing something after the decorated function')\n", 1140 " print('Doing something after the decorated function')\n",
813 " return retval\n", 1141 " return retval # returning the return value of the original (decorated) function\n",
814 " return decorated\n", 1142 " return decorated\n",
1143 "```\n",
815 "\n", 1144 "\n",
1145 "once having a decorator:\n",
1146 "\n",
1147 "```python\n",
816 "def my_function():\n", 1148 "def my_function():\n",
817 " print('Alice')\n", 1149 " print('Alice')\n",
818 "\n", 1150 "\n",
@@ -835,7 +1167,7 @@
835 }, 1167 },
836 { 1168 {
837 "cell_type": "code", 1169 "cell_type": "code",
838 "execution_count": 104, 1170 "execution_count": 60,
839 "id": "4346260d-76af-437e-9c10-1c1d0c478695", 1171 "id": "4346260d-76af-437e-9c10-1c1d0c478695",
840 "metadata": {}, 1172 "metadata": {},
841 "outputs": [], 1173 "outputs": [],
@@ -864,6 +1196,7 @@
864 "\n", 1196 "\n",
865 "\n", 1197 "\n",
866 "@requires_access(access_secret='b28cfeaa65b73cf')\n", 1198 "@requires_access(access_secret='b28cfeaa65b73cf')\n",
1199 "@is_admin\n",
867 "def sensitive_function(data, **kwargs):\n", 1200 "def sensitive_function(data, **kwargs):\n",
868 " \"\"\"very sensitive function\"\"\"\n", 1201 " \"\"\"very sensitive function\"\"\"\n",
869 " db.save(data)" 1202 " db.save(data)"
diff --git a/notebooks/python/python_oo.ipynb b/notebooks/python/python_oo.ipynb
index fe717a9..7147a87 100644
--- a/notebooks/python/python_oo.ipynb
+++ b/notebooks/python/python_oo.ipynb
@@ -106,7 +106,7 @@
106 "\n", 106 "\n",
107 "- class variable - attribute of which a single copy exists, regardless of how many instances of the class exist\n", 107 "- class variable - attribute of which a single copy exists, regardless of how many instances of the class exist\n",
108 "\n", 108 "\n",
109 "- object / instance variable - attribute for which each instantiated object of the class has a separate copy, or instance\n", 109 "- object / instance variable, object / instance attribute - attribute for which each instantiated object of the class has a separate copy, or instance\n",
110 "\n", 110 "\n",
111 "- method - member function - function that is an attribute" 111 "- method - member function - function that is an attribute"
112 ] 112 ]
@@ -208,7 +208,7 @@
208 }, 208 },
209 { 209 {
210 "cell_type": "code", 210 "cell_type": "code",
211 "execution_count": 70, 211 "execution_count": 1,
212 "id": "391e816e-c53b-454b-9e9f-3587234f1fea", 212 "id": "391e816e-c53b-454b-9e9f-3587234f1fea",
213 "metadata": {}, 213 "metadata": {},
214 "outputs": [ 214 "outputs": [
@@ -241,6 +241,8 @@
241 " initialization of the base class part of the instance;\n", 241 " initialization of the base class part of the instance;\n",
242 " for example: super().__init__([args...]).\n", 242 " for example: super().__init__([args...]).\n",
243 " \"\"\"\n", 243 " \"\"\"\n",
244 " # defines instance attributes that will \"live\" as long as\n",
245 " # the object / instance \"lives\" \n",
244 " self._x = x # _ indicates \"protected\" attribute\n", 246 " self._x = x # _ indicates \"protected\" attribute\n",
245 " self.__y = y # not a typo: __ indicates \"private\" attribute.\n", 247 " self.__y = y # not a typo: __ indicates \"private\" attribute.\n",
246 "\n", 248 "\n",
@@ -306,7 +308,7 @@
306 }, 308 },
307 { 309 {
308 "cell_type": "code", 310 "cell_type": "code",
309 "execution_count": 71, 311 "execution_count": 2,
310 "id": "e82feefb-025d-4cbb-a8ac-ddc3cc01269c", 312 "id": "e82feefb-025d-4cbb-a8ac-ddc3cc01269c",
311 "metadata": {}, 313 "metadata": {},
312 "outputs": [ 314 "outputs": [
@@ -389,7 +391,7 @@
389 }, 391 },
390 { 392 {
391 "cell_type": "code", 393 "cell_type": "code",
392 "execution_count": 72, 394 "execution_count": 3,
393 "id": "71a90ec6-3cc0-441e-a866-c2c2b9984559", 395 "id": "71a90ec6-3cc0-441e-a866-c2c2b9984559",
394 "metadata": {}, 396 "metadata": {},
395 "outputs": [ 397 "outputs": [
@@ -503,7 +505,7 @@
503 }, 505 },
504 { 506 {
505 "cell_type": "code", 507 "cell_type": "code",
506 "execution_count": 73, 508 "execution_count": 4,
507 "id": "a4d2735d-d167-4f43-ad55-cb3d13ece2dc", 509 "id": "a4d2735d-d167-4f43-ad55-cb3d13ece2dc",
508 "metadata": {}, 510 "metadata": {},
509 "outputs": [ 511 "outputs": [
@@ -546,7 +548,7 @@
546 }, 548 },
547 { 549 {
548 "cell_type": "code", 550 "cell_type": "code",
549 "execution_count": 74, 551 "execution_count": 5,
550 "id": "a6ead5e6-e987-4bda-bf48-30f91877278d", 552 "id": "a6ead5e6-e987-4bda-bf48-30f91877278d",
551 "metadata": {}, 553 "metadata": {},
552 "outputs": [ 554 "outputs": [
@@ -605,7 +607,7 @@
605 }, 607 },
606 { 608 {
607 "cell_type": "code", 609 "cell_type": "code",
608 "execution_count": 75, 610 "execution_count": 6,
609 "id": "11f6a3fb-64d7-40a9-a130-27548ec4b802", 611 "id": "11f6a3fb-64d7-40a9-a130-27548ec4b802",
610 "metadata": {}, 612 "metadata": {},
611 "outputs": [ 613 "outputs": [
@@ -683,7 +685,7 @@
683 }, 685 },
684 { 686 {
685 "cell_type": "code", 687 "cell_type": "code",
686 "execution_count": 76, 688 "execution_count": 7,
687 "id": "c345a69f-02da-40e7-bb37-c0511b6af096", 689 "id": "c345a69f-02da-40e7-bb37-c0511b6af096",
688 "metadata": {}, 690 "metadata": {},
689 "outputs": [ 691 "outputs": [
@@ -774,7 +776,7 @@
774 }, 776 },
775 { 777 {
776 "cell_type": "code", 778 "cell_type": "code",
777 "execution_count": 77, 779 "execution_count": 8,
778 "id": "44d47e1c-1a06-4577-8db6-6ec78ce5cef8", 780 "id": "44d47e1c-1a06-4577-8db6-6ec78ce5cef8",
779 "metadata": {}, 781 "metadata": {},
780 "outputs": [ 782 "outputs": [
@@ -948,7 +950,7 @@
948 }, 950 },
949 { 951 {
950 "cell_type": "code", 952 "cell_type": "code",
951 "execution_count": 78, 953 "execution_count": 9,
952 "id": "e6076925-75f0-456c-aed5-7db0a24a67a1", 954 "id": "e6076925-75f0-456c-aed5-7db0a24a67a1",
953 "metadata": {}, 955 "metadata": {},
954 "outputs": [ 956 "outputs": [
@@ -1059,7 +1061,7 @@
1059 }, 1061 },
1060 { 1062 {
1061 "cell_type": "code", 1063 "cell_type": "code",
1062 "execution_count": 79, 1064 "execution_count": 13,
1063 "id": "cf79617a-95d2-48f2-be66-fa1fa34e4e04", 1065 "id": "cf79617a-95d2-48f2-be66-fa1fa34e4e04",
1064 "metadata": {}, 1066 "metadata": {},
1065 "outputs": [ 1067 "outputs": [
@@ -1067,7 +1069,30 @@
1067 "name": "stdout", 1069 "name": "stdout",
1068 "output_type": "stream", 1070 "output_type": "stream",
1069 "text": [ 1071 "text": [
1070 "Simeon's MRO: (<class '__main__.Simeon'>, <class '__main__.Mother'>, <class '__main__.Grandmother1'>, <class '__main__.Grandfather1'>, <class '__main__.Father'>, <class '__main__.Grandmother2'>, <class '__main__.Grandfather2'>, <class '__main__.Adam'>, <class '__main__.Eve'>, <class 'object'>)\n" 1072 "Simeon's MRO: (<class '__main__.Simeon'>, <class '__main__.Mother'>, <class '__main__.Grandmother1'>, <class '__main__.Grandfather1'>, <class '__main__.Father'>, <class '__main__.Grandmother2'>, <class '__main__.Grandfather2'>, <class '__main__.Adam'>, <class '__main__.Eve'>, <class 'object'>)\n",
1073 "Help on Simeon in module __main__ object:\n",
1074 "\n",
1075 "class Simeon(Mother, Father)\n",
1076 " | Method resolution order:\n",
1077 " | Simeon\n",
1078 " | Mother\n",
1079 " | Grandmother1\n",
1080 " | Grandfather1\n",
1081 " | Father\n",
1082 " | Grandmother2\n",
1083 " | Grandfather2\n",
1084 " | Adam\n",
1085 " | Eve\n",
1086 " | builtins.object\n",
1087 " | \n",
1088 " | Data descriptors inherited from Adam:\n",
1089 " | \n",
1090 " | __dict__\n",
1091 " | dictionary for instance variables (if defined)\n",
1092 " | \n",
1093 " | __weakref__\n",
1094 " | list of weak references to the object (if defined)\n",
1095 "\n"
1071 ] 1096 ]
1072 } 1097 }
1073 ], 1098 ],
@@ -1108,12 +1133,14 @@
1108 " pass\n", 1133 " pass\n",
1109 "\n", 1134 "\n",
1110 "\n", 1135 "\n",
1111 "print(f\"Simeon's MRO: {Simeon.__mro__}\")" 1136 "print(f\"Simeon's MRO: {Simeon.__mro__}\")\n",
1137 "simeon = Simeon()\n",
1138 "help(simeon)"
1112 ] 1139 ]
1113 }, 1140 },
1114 { 1141 {
1115 "cell_type": "code", 1142 "cell_type": "code",
1116 "execution_count": 80, 1143 "execution_count": 11,
1117 "id": "95a1d0cc-0006-4ddc-b08d-d0b8b02acfba", 1144 "id": "95a1d0cc-0006-4ddc-b08d-d0b8b02acfba",
1118 "metadata": {}, 1145 "metadata": {},
1119 "outputs": [ 1146 "outputs": [
@@ -1179,7 +1206,7 @@
1179 }, 1206 },
1180 { 1207 {
1181 "cell_type": "code", 1208 "cell_type": "code",
1182 "execution_count": 81, 1209 "execution_count": 12,
1183 "id": "38066107-0190-4383-ba14-a4e9cd454a9c", 1210 "id": "38066107-0190-4383-ba14-a4e9cd454a9c",
1184 "metadata": {}, 1211 "metadata": {},
1185 "outputs": [ 1212 "outputs": [
@@ -1189,7 +1216,23 @@
1189 "text": [ 1216 "text": [
1190 "Using mock data\n", 1217 "Using mock data\n",
1191 "Extracting production plans from data\n", 1218 "Extracting production plans from data\n",
1192 "some magic is happening here...\n", 1219 "some magic is happening here...\n"
1220 ]
1221 },
1222 {
1223 "data": {
1224 "text/plain": [
1225 "'{}'"
1226 ]
1227 },
1228 "execution_count": 12,
1229 "metadata": {},
1230 "output_type": "execute_result"
1231 },
1232 {
1233 "name": "stdout",
1234 "output_type": "stream",
1235 "text": [
1193 "(<class '__main__.MockedButStillCoolTSPreprocessor'>, <class '__main__.CoolTSPreprocessor'>, <class '__main__.MockConnectionManager'>, <class '__main__.ConnectionManager'>, <class 'object'>)\n" 1236 "(<class '__main__.MockedButStillCoolTSPreprocessor'>, <class '__main__.CoolTSPreprocessor'>, <class '__main__.MockConnectionManager'>, <class '__main__.ConnectionManager'>, <class 'object'>)\n"
1194 ] 1237 ]
1195 } 1238 }
@@ -1248,7 +1291,7 @@
1248 "name": "python", 1291 "name": "python",
1249 "nbconvert_exporter": "python", 1292 "nbconvert_exporter": "python",
1250 "pygments_lexer": "ipython3", 1293 "pygments_lexer": "ipython3",
1251 "version": "3.11.0" 1294 "version": "3.10.8"
1252 } 1295 }
1253 }, 1296 },
1254 "nbformat": 4, 1297 "nbformat": 4,
diff --git a/notebooks/sqlalchemy/sqlalchemy.ipynb b/notebooks/sqlalchemy/sqlalchemy.ipynb
index 8bb8333..92b2d56 100644
--- a/notebooks/sqlalchemy/sqlalchemy.ipynb
+++ b/notebooks/sqlalchemy/sqlalchemy.ipynb
@@ -182,9 +182,7 @@
182 "source": [ 182 "source": [
183 "from sqlalchemy import Column, Table\n", 183 "from sqlalchemy import Column, Table\n",
184 "from sqlalchemy import DateTime, ForeignKey, Integer, Numeric, String\n", 184 "from sqlalchemy import DateTime, ForeignKey, Integer, Numeric, String\n",
185 "from sqlalchemy.orm import relationship\n", 185 "from sqlalchemy.orm import declarative_base, relationship\n",
186 "\n",
187 "from sqlalchemy.ext.declarative import declarative_base\n",
188 "\n", 186 "\n",
189 "Base = declarative_base()\n", 187 "Base = declarative_base()\n",
190 "\n", 188 "\n",
@@ -767,7 +765,7 @@
767 "name": "python", 765 "name": "python",
768 "nbconvert_exporter": "python", 766 "nbconvert_exporter": "python",
769 "pygments_lexer": "ipython3", 767 "pygments_lexer": "ipython3",
770 "version": "3.8.10" 768 "version": "3.10.8"
771 } 769 }
772 }, 770 },
773 "nbformat": 4, 771 "nbformat": 4,