summaryrefslogtreecommitdiff
path: root/reveal.js/python.html
diff options
context:
space:
mode:
authorSimeon Simeonov2022-09-10 18:19:22 +0200
committerSimeon Simeonov2022-09-10 18:19:22 +0200
commit4ef55e4d52e06d071354bd7f6f6ba0a86243fc0e (patch)
treea8e961da78d84163cbb563f9e106d95314bea5e8 /reveal.js/python.html
parent29c52d98bf7feb132a1857cce2058ec7134e4b0f (diff)
Add reveal.js/dist/theme/jupyter.css and reveal.js/python-oo.html
Diffstat (limited to 'reveal.js/python.html')
-rw-r--r--reveal.js/python.html264
1 files changed, 256 insertions, 8 deletions
diff --git a/reveal.js/python.html b/reveal.js/python.html
index 5190dfb..d27cd49 100644
--- a/reveal.js/python.html
+++ b/reveal.js/python.html
@@ -44,9 +44,9 @@
44 <h2>Preliminary plan</h2> 44 <h2>Preliminary plan</h2>
45 </br> 45 </br>
46 <ul> 46 <ul>
47 <li><p>Basics: About the language, the Python eco-system, types, scopes, modules and functions</p></li> 47 <li><p><b>Basics: About the language, the Python eco-system, types, modules, functions, scopes, decorators, string formatting</b></p></li>
48 <li><p>Control flow: if / for / while / try, iterators, decorators, "tactical programming" tips</p></li> 48 <li><p>Object-oriented programming in Python: How Python "really works"</p></li>
49 <li><p>Object orientation: How Python "really works"</p></li> 49 <li><p>Control flow: if / for / while / try, iterators, "tactical programming" tips</p></li>
50 <li><p>A brief tour through Python's standard library</p></li> 50 <li><p>A brief tour through Python's standard library</p></li>
51 <li><p>Code design and best practices: How to design your code</p></li> 51 <li><p>Code design and best practices: How to design your code</p></li>
52 </ul> 52 </ul>
@@ -231,6 +231,8 @@
231 # load, use and unload the virtual environment 231 # load, use and unload the virtual environment
232 source my_virtual_env/bin/activate 232 source my_virtual_env/bin/activate
233 pip install sqlalchemy 233 pip install sqlalchemy
234 # install package from a custom repository (https://artifactory.fifty.eu)
235 pip install --index-url=https://artifactory.fifty.eu/artifactory/api/pypi/pypi/simple/ odin-data-access
234 deactivate 236 deactivate
235 237
236 # one can alternatively use the python "wrapper" of the virtual env 238 # one can alternatively use the python "wrapper" of the virtual env
@@ -344,22 +346,173 @@
344 def addl(a, b): 346 def addl(a, b):
345 """Function for adding two lists""" 347 """Function for adding two lists"""
346 result = a + b 348 result = a + b
347 a += [5] 349 a += [5] # in this case equal to: a.append(5)
348 return result 350 return result
349 351
350 a_param = [9] 352 a_param = [9]
351 b_param = [-2] 353 b_param = [-2]
352 addl(a_param, b_param) # Out: [9, -2] 354 addl(a_param, b_param) # Out: [9, -2]
353 # lists are mutable and a_param will be changed 355 # lists are mutable and a_param will be changed
354 print(a_param) # Out: [5] 356 print(a_param) # Out: [9, 5]
355 </code> 357 </code>
356 </pre> 358 </pre>
357 </section> 359 </section>
358 360
359 <section> 361 <section>
360 <h2>Functions</h2> 362 <h2>Functions (cont ...)</h2>
363 </br>
364 <h3>Parameters and arguments</h3>
365 <pre data-id="code-animation">
366 <code class="python" data-trim type="text/template">
367 def add(a, b):
368 """Function for adding integers"""
369 return a + b
370 my_result = add(2, 5) # positional arguments (parameters)
371 my_result = add(b=5, a=2) # keyword arguments (parameters)
372 my_tuple = (2, 5)
373 my_dict = {'b': 5, 'a': 2}
374 my_result = add(*my_tuple) # unpacked and assigned to the positional arguments
375 my_result = add(**my_dict) # unpacked and assigned to the kw. arguments
376
377 def add(a, b=5):
378 """Function for adding integers"""
379 return a + b
380 my_result = add(2)
381 # ... and the rest of the examples above will work
382
383 def add(a, *args, **kwargs):
384 """Function for adding integers"""
385 if args:
386 b = args[0]
387 elif 'b' in kwargs:
388 b = kwargs['b']
389 return a + b
390 my_result = add(2, 5, 9, 11) # 5 assigned to args[0]
391 my_result = add(2, b=5, c=9, d=11) # 5 assigned to kwargs['b']
392 my_result = add(2, b=5, 9, 11) # SyntaxError: positional argument follows keyword argument
393 </code>
394 </pre>
395 </section>
396
397 <section>
398 <h2>Functions (cont ...)</h2>
399 </br>
400 <h3>Docstrings annotations and other hints</h3>
401 <pre data-id="code-animation">
402 <code class="python" data-trim type="text/template">
403 def decrypt(password: str, edata: str) -> str:
404 """
405 Decrypts `edata` using `password`.
406
407 `edata` is in the following format:
408 enc-val$`version-num`$`bas64-salt`$`base64-encrypted_data`
409
410 :param password: The password to generate the key with
411 :type password: str
412
413 :param edata: The data to be decrypted
414 :type edata: str
415
416 :raises EtoolkitInstanceError: If the encryption format is unsupported
417
418 :return: The output string / decrypted data
419 :rtype: str
420 """
421 if not edata.startswith('enc-val$1$'):
422 raise EtoolkitInstanceError('Unsupported encryption format')
423 # some more code magic coming after....
424 # ...
425 # ..
426 return decrypted_str
427 </code>
428 </pre>
429 </section>
430
431 <section>
432 <h2>Functions (cont ...)</h2>
433 </br>
434 <h3>Using <em>typing</em> for more advanced / flexible hinting</h3>
435 <pre data-id="code-animation">
436 <code class="python" data-trim type="text/template">
437 import typing
438
439 Basestring = typing.Union[str, bytes]
440
441 def decrypt(password: Basestring, edata: str) -> str:
442 pass
443
444
445 from typing import Union
446
447 def decrypt(password: Union[str, bytes], edata: str) -> str:
448 """Generic documentation. No need for pass"""
449
450 # Python >= 3.10 only
451 def decrypt(password: str | bytes, edata: str) -> str:
452 """Generic documentation. No need for pass"""
453 </code>
454 </pre>
455 </section>
456
457 <section>
458 <h2>Functions (cont ...)</h2>
459 <h4>Functions as parameters / arguments, lambdas and returning multiple values</h4>
460 <pre data-id="code-animation">
461 <code class="python" data-trim type="text/template">
462 def fetch_the_first_letter(input_str: str) -> str:
463 """Fetches the first letter of the string input_str or 'x'""""
464 try:
465 return input_str[0]
466 except Exception:
467 return 'x'
468 letter_list = list(map(fetch_the_first_letter, ['foo', 'bar', 'test'])) # Out: ['f', 'b', 't']
469 </code>
470 </pre>
471 <p>Small anonymous functions can be created with the <em>lambda</em> keyword</p>
472 <pre data-id="code-animation">
473 <code class="python" data-trim type="text/template">
474 letter_list = list(map(lambda x: x[0], ['foo', 'bar', 'test'])) # Out: ['f', 'b', 't']
475 </code>
476 </pre>
477 <p>Functions in Python are <em>callable objects</em>. Callable objects can be created by defining the <em>__call__</em> method. More on that later in the course...</p>
478 <p>A function can return multiple values by implicitly returning a tuple:</p>
479 <pre data-id="code-animation">
480 <code class="python" data-trim type="text/template">
481 def square_cube(x):
482 """returns x, x^2 and x^3"""
483 return x, x**2, x**3
484 numbers = square_cube(5) # Out: (5, 25, 125)
485 num, sqnum, cbnum = square_cube(5) # unpacking the tuple
486 </code>
487 </pre>
488 </section>
489
490 <section>
491 <h2>Functions (cont ...)</h2>
361 </br> 492 </br>
362 <h3>To be continued in the next episode....</h3> 493 <h3>Enclosing and nested functions</h3>
494 <p>Can be used as:</p>
495 <ul>
496 <li>regular functions within functions</li>
497 <li>dynamic function factories</li>
498 </ul>
499 <pre data-id="code-animation">
500 <code class="python" data-trim type="text/template">
501 def get_multiplier_of(base: int) -> str:
502 """the function enclosing its nested functions"""
503
504 def multiplier_function(x):
505 """a nested function"""
506 return base * x
507
508 return multiplier_function
509
510 times3 = get_multiplier_of(3)
511 times5 = get_multiplier_of(5)
512 print(times3(3)) # Out: 9
513 print(times5(3)) # Out: 15
514 </code>
515 </pre>
363 </section> 516 </section>
364 517
365 <section> 518 <section>
@@ -399,7 +552,102 @@
399 </section> 552 </section>
400 553
401 <section> 554 <section>
402 <h1>Q &amp; A</h1> 555 <h2>Decorators</h2>
556 <p>Decorators can be used to modify the behavior of the objects they decorate. Decorators can be implemented either by using classes or by using nested functions.</p>
557 <pre data-id="code-animation">
558 <code class="python" data-trim type="text/template">
559 def my_decorator(func):
560
561 def decorated():
562 print('Doing something before the decorated function')
563 retval = func()
564 print('Doing something after the decorated function')
565 return retval
566 return decorated
567
568 def my_function():
569 print('Alice')
570
571 my_function = my_decorator(my_function)
572 my_function()
573 </code>
574 </pre>
575 <p>... may be dificult to read / understand, while:</p>
576 <pre data-id="code-animation">
577 <code class="python" data-trim type="text/template">
578 @my_decorator
579 def my_function():
580 print('Alice')
581
582 my_function()
583 </code>
584 </pre>
585 <p>... may be easier</p>
586 </section>
587
588 <section>
589 <h2>Decorators (cont ...)</h2>
590 </br>
591 <h3>A complete example</h3>
592 <pre data-id="code-animation">
593 <code class="python" data-trim type="text/template">
594 import sys
595 from functools import wraps
596
597 def requires_access(access_secret: str):
598
599 def api_access_decorator(f):
600
601 @wraps(f)
602 def decorated(*args, **kwargs):
603 if 'secret' not in kwargs:
604 sys.exit('No secret provided')
605 if not kwargs['secret'] or kwargs['secret'] != access_secret:
606 sys.exit("Secret doesn't match")
607 # return f(args[0], **kwargs)
608 return f(*args, **kwargs)
609
610 return decorated
611
612 return api_access_decorator
613
614
615 @requires_access(access_secret='b28cfeaa65b73cf')
616 def sensitive_function(data, **kwargs):
617 """very sensitive function"""
618 db.save(data)
619 </code>
620 </pre>
621 </section>
622
623 <section>
624 <h2>String formatting</h2>
625 </br>
626 <h3>The old ways...</h3>
627 <pre data-id="code-animation">
628 <code class="python" data-trim type="text/template">
629 f = 6.57865
630 i = 27
631 s = 'another string'
632
633
634 '%s - %d - %5.2f' % (s, i, f) # Out: 'another string - 27 - 6.58'
635
636 # still used in:
637 logger.debug("%d - %s", event.id, message)
638
639
640 '{} - {} - {:5.2f}'.format(s, i, f) # implicit
641 '{0} - {1} - {2:5.2f}'.format(s, i, f) # explicit
642 '{my_str} - {i} - {fl:5.2f}'.format(my_str=s, fl=f, i=i) # keyword
643 # Out: 'another string - 27 - 6.58'
644
645
646 # modern Python >= 3.6 f-strings
647 f'{s} - {i} - {f:5.2f}' # Out: 'another string - 27 - 6.58'
648 </code>
649 </pre>
650 <p>See <a href="https://docs.python.org/3/library/string.html#formatspec">https://docs.python.org/3/library/string.html#formatspec</a> for the complete format specification</p>
403 </section> 651 </section>
404 652
405 </div> 653 </div>