avancé
This commit is contained in:
parent
069c1edb43
commit
8d2bba04e3
|
@ -364,77 +364,82 @@ class Counter:
|
|||
```
|
||||
|
||||
|
||||
# La suite
|
||||
## Pendant qu'on parle de `yield`
|
||||
|
||||
Connaissez-vous `yield from` ?
|
||||
|
||||
|
||||
- Langage, syntaxe, datamodel
|
||||
- f-strings, .format
|
||||
- else du for, while et try
|
||||
- User defined exceptions
|
||||
- functions: *args, **kwargs
|
||||
- unpacking, deep unpacking, starred unpacking
|
||||
- packing (* dans des listes et ** dans des dicts)
|
||||
- Imprécision des float IEEE 754
|
||||
- is vs ==, `id`
|
||||
- Le protocole d'itération, les générateurs
|
||||
- yield
|
||||
- yield from
|
||||
- string interning
|
||||
- types immuables
|
||||
- Les décorateurs, les décorateurs paramétrés
|
||||
- global, nonlocal
|
||||
- closures
|
||||
- @property
|
||||
- Les gestionnaires de contexte, montrer `with ... as (a, b):`
|
||||
- Datamodel / Special method names (depends on classes) : en parler
|
||||
en abordant les différents sujets.
|
||||
## Pendant qu'on parle de `for`
|
||||
|
||||
- Classes et Objets
|
||||
- staticmethod vs classmethod
|
||||
- héritage et MRO, coopération des classes avec super()
|
||||
- métaclasses
|
||||
- Les descripteurs
|
||||
Connaissez-vous le `else` du `for` ?
|
||||
|
||||
- L'encodage
|
||||
- Unicode, UTF-8
|
||||
- str, bytes
|
||||
Notes:
|
||||
|
||||
- Packaging
|
||||
- pip install -e .
|
||||
- Rappel sur la distinction module / package, venv / pip
|
||||
- setuptools, wheel, sdist, bidst_wheel
|
||||
- __main__
|
||||
- cookiecutter : docs/, tests/, README, setup.cfg, setup.py, ...
|
||||
- List comprehension avancé
|
||||
- Double for, double if, walrus
|
||||
- Multiprocessing / Multithreading / Asyncio
|
||||
- IO Bound vs CPU Bound
|
||||
- Locks vs Queues
|
||||
- Code quality
|
||||
- import this, explicit is better
|
||||
- TDD
|
||||
- -Xdev
|
||||
- black, ..., pass
|
||||
- pytest, doctest
|
||||
- pytest-cov
|
||||
- hypothesis
|
||||
- flake8
|
||||
- flake8-bugbear
|
||||
- tox
|
||||
- mypy
|
||||
- black
|
||||
- pdb, breakpoint()
|
||||
- EAFP, LBYL
|
||||
- Performance
|
||||
- Les types natifs : Leur complexité algorithmique
|
||||
- Cython
|
||||
- pypy
|
||||
- cffi
|
||||
- cprofile / pstats
|
||||
- Libs
|
||||
- re
|
||||
- argparse
|
||||
- pathlib
|
||||
- logging
|
||||
- numpy
|
||||
- jupyter
|
||||
Il ne s'exécute que si le `for` sort sans `break`.
|
||||
|
||||
|
||||
## `else`
|
||||
|
||||
```python
|
||||
n = 13
|
||||
for i in range(2, n - 1):
|
||||
if n % i == 0:
|
||||
print(f"{n} is not prime")
|
||||
break
|
||||
else:
|
||||
print(f"{n} is prime")
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
Typiquement utile lors des recherches, la sémantique :
|
||||
- Trouvé, plus besoin de chercher, break.
|
||||
- else: pas trouvé.
|
||||
|
||||
Fonctionne aussi sur le while.
|
||||
|
||||
Ah j'ai utilisé une f-string.
|
||||
|
||||
|
||||
## Literal String Interpolation
|
||||
|
||||
```python
|
||||
>>> f"{42:08b}"
|
||||
00101010
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
Attention aux ':' et '!' dans l'expression, bien que ce soit accepté
|
||||
si c'est entre guillemet, crochets, parenthèses, ... sinon toute
|
||||
expression Python est autorisée (comme avec .format, mais avec .format
|
||||
c'est plus évident).
|
||||
|
||||
|
||||
## Literal String Interpolation
|
||||
|
||||
```python
|
||||
>>> f"{(lambda x: x.upper())('hello'):^11}"
|
||||
' HELLO '
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
Attention à rester lisible, mais ici le `:` de la lambda est entre
|
||||
parenthèses, donc c'est bon.
|
||||
|
||||
En parlant de parenthèse, fermons une parenthèse.
|
||||
|
||||
|
||||
## On parlais d'itérables
|
||||
|
||||
Si on parlais d'unpacking ?
|
||||
|
||||
Notes:
|
||||
|
||||
Pour se remémorer ces choses, cherchez les PEPs, typiquement la 448, la 3132, ...
|
||||
|
||||
Parler de `deep unpacking`.
|
||||
|
||||
|
||||
## Ça peut rappeler *args et **kwargs
|
69
avancé/2-object.md
Normal file
69
avancé/2-object.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Les objets
|
||||
|
||||
## Rappels
|
||||
|
||||
- Keep it simple.
|
||||
- Flat is better than nested.
|
||||
|
||||
|
||||
## `classmethod` vs `staticmethod`
|
||||
|
||||
## La MRO
|
||||
|
||||
## `super()` !
|
||||
|
||||
Notes:
|
||||
|
||||
Et la coopération.
|
||||
|
||||
|
||||
## Le protocole « descripteur »
|
||||
|
||||
- `object.__get__(self, instance, owner=None)`
|
||||
- `object.__set__(self, instance, value)`
|
||||
|
||||
Notes:
|
||||
|
||||
Et `__delete__` et `__setname__`.
|
||||
|
||||
- instance... c'est l'instance.
|
||||
- owner, c'est le type, il est toujours connu donc "devrait" toujours être donné
|
||||
- Si instance n'est pas donnée, c'est qu'on accède à l'attribut sur le type.
|
||||
|
||||
|
||||
## Métaclasses
|
||||
|
||||
Puisqu'une classe est un objet, une métaclasse c'est le type du type.
|
||||
|
||||
Notes:
|
||||
|
||||
En initiation on dit "ça ne vous servira pas". En avancé on dit
|
||||
`__init_subclass__` couvrira tous vos besoins.
|
||||
|
||||
|
||||
## Métaclasse
|
||||
|
||||
- `__new__` et `__init__` d'une classe servent à personaliser l'instance.
|
||||
- `__new__` et `__init__` d'une metaclasse servent à personalier une classe.
|
||||
|
||||
Notes:
|
||||
|
||||
```python
|
||||
class M(type):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
print(f"meta.__new__(*{args}, **{kwargs})")
|
||||
return super().__new__(cls, *args, **kwargs)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
print(f"meta.__init__(*{args}, **{kwargs})")
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
class MyCls(metaclass=M):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
print(f"cls.__new__(*{args}, **{kwargs})")
|
||||
return super().__new__(cls, *args, **kwargs)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
print(f"cls.__init__(*{args}, **{kwargs})")
|
||||
super().__init__(*args, **kwargs)
|
||||
```
|
185
avancé/3-language.md
Normal file
185
avancé/3-language.md
Normal file
|
@ -0,0 +1,185 @@
|
|||
# Langage
|
||||
|
||||
## `id` et `is`
|
||||
|
||||
Notes:
|
||||
|
||||
- `is` pour les singletsons `None`, `True`, `False`.
|
||||
- `id` : identifiant unique, l'adresse mémoire en CPython.
|
||||
- `is` sémantiquement est donc `id(left) == id(right)` mais attention au GC.
|
||||
|
||||
|
||||
## Parenthèse sur les singletons
|
||||
|
||||
Notes:
|
||||
|
||||
Un module est un singleton.
|
||||
|
||||
|
||||
## String interning
|
||||
|
||||
```python3
|
||||
a = "Bonjour !"
|
||||
b = "Bonjour !"
|
||||
a is b
|
||||
```
|
||||
|
||||
?
|
||||
|
||||
Notes:
|
||||
|
||||
- C'est dépendant de l'implémentation, ça change d'une version à l'autre de Python.
|
||||
- Les chaînes ne contenant que des [a-zA-Z0-9_] sont internées.
|
||||
|
||||
|
||||
## IEEE 754
|
||||
|
||||
```python
|
||||
f"http://{.1 + .2}.com"
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
Notez ! Et au besoin utilisez le module Decimal.
|
||||
|
||||
|
||||
## Définir vos propres exceptions
|
||||
|
||||
Il suffit d'hériter d'`Exception`, rien de plus.
|
||||
|
||||
```
|
||||
>>> class DBError(Exception): pass
|
||||
...
|
||||
>>> raise DBError("No such entry")
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
__main__.DBError: No such entry
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
library/exceptions.html → hierarchy
|
||||
|
||||
|
||||
## try, finally, else, except
|
||||
|
||||
Dans quel ordre ?
|
||||
|
||||
Notes: Oui, il y a un else ici aussi.
|
||||
|
||||
|
||||
## try, except, else, finally
|
||||
|
||||
## Les décorateurs
|
||||
|
||||
```python
|
||||
with open("/etc/hosts") as f:
|
||||
f.read()
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
En initiation on apprend a les utiliser.
|
||||
En avancé on apprend à en faire.
|
||||
|
||||
## Les décorateurs
|
||||
|
||||
Faire ses propres décorateurs.
|
||||
|
||||
Notes:
|
||||
|
||||
Leur faire implémenter un décorateur @clock.
|
||||
```python
|
||||
def clock(func):
|
||||
def clocked(*args):
|
||||
t0 = time.perf_counter()
|
||||
result = func(*args)
|
||||
elapsed = time.perf_counter() -t0
|
||||
name = func.__name__
|
||||
arg_str = ', '.join(repr(arg) for arg in args)
|
||||
print(f"[{elapsed:.08f}s] {name}({arg_str}) -> {result!r}")
|
||||
return result
|
||||
return clocked
|
||||
```
|
||||
|
||||
|
||||
## Les décorateurs
|
||||
|
||||
Faire ses décorateurs paramétrés.
|
||||
|
||||
Notes:
|
||||
|
||||
Leur faire implémenter @memoize qui prend paramètre une limite.
|
||||
|
||||
En profiter pour parler de `global`, `nonlocal`, et des closures.
|
||||
|
||||
|
||||
## Les décorateurs
|
||||
|
||||
Les utiliser pour leurs effets de bord.
|
||||
|
||||
Notes:
|
||||
|
||||
`@route("/")` par exemple.
|
||||
|
||||
|
||||
# La suite
|
||||
|
||||
|
||||
- Langage, syntaxe, datamodel
|
||||
- Les décorateurs, les décorateurs paramétrés
|
||||
- global, nonlocal
|
||||
- closures
|
||||
- @property
|
||||
- Les gestionnaires de contexte, montrer `with ... as (a, b):`
|
||||
- Datamodel / Special method names (depends on classes) : en parler
|
||||
en abordant les différents sujets.
|
||||
|
||||
- L'encodage
|
||||
- Unicode, UTF-8
|
||||
- str, bytes
|
||||
|
||||
- Packaging
|
||||
- pip install -e .
|
||||
- Rappel sur la distinction module / package, venv / pip
|
||||
- setuptools, wheel, sdist, bidst_wheel
|
||||
- __main__
|
||||
- cookiecutter : docs/, tests/, README, setup.cfg, setup.py, ...
|
||||
|
||||
- List comprehension avancé
|
||||
- Double for, double if, walrus
|
||||
|
||||
- Multiprocessing / Multithreading / Asyncio
|
||||
- IO Bound vs CPU Bound
|
||||
- Locks vs Queues
|
||||
|
||||
- Code quality
|
||||
- import this, explicit is better
|
||||
- TDD
|
||||
- -Xdev
|
||||
- black, ..., pass
|
||||
- pytest, doctest
|
||||
- pytest-cov
|
||||
- hypothesis
|
||||
- flake8
|
||||
- flake8-bugbear
|
||||
- tox
|
||||
- mypy
|
||||
- black
|
||||
- pdb, breakpoint()
|
||||
- EAFP, LBYL
|
||||
|
||||
- Performance
|
||||
- Les types natifs : Leur complexité algorithmique
|
||||
- Cython
|
||||
- pypy
|
||||
- cffi
|
||||
- cprofile / pstats
|
||||
|
||||
- Libs
|
||||
- re
|
||||
- argparse
|
||||
- pathlib
|
||||
- logging
|
||||
- numpy
|
||||
- jupyter
|
|
@ -41,7 +41,7 @@ static: $(HTML) index.html
|
|||
output/%.html: %.md $(REVEAL_JS)
|
||||
mkdir -p output/
|
||||
python3 ../md2reveal/md2reveal.py --revealjs-url "reveal.js-$(REVEAL_JS_VERSION)" $< $@
|
||||
[ -d static ] && cp -a static output
|
||||
if [ -d static ]; then cp -a static output; fi
|
||||
|
||||
.PHONY: rsync
|
||||
rsync: static
|
||||
|
|
|
@ -74,192 +74,14 @@
|
|||
|
||||
// Full list of configuration options available at:
|
||||
// https://github.com/hakimel/reveal.js#configuration
|
||||
Reveal.initialize({
|
||||
{% if controls %}
|
||||
// Display controls in the bottom right corner
|
||||
controls: {{ controls }},
|
||||
{% endif %}
|
||||
{% if progress %}
|
||||
// Display a presentation progress bar
|
||||
progress: {{ progress }},
|
||||
{% endif %}
|
||||
{% if slideNumber %}
|
||||
// Display the page number of the current slide
|
||||
slideNumber: {{ slideNumber }},
|
||||
{% endif %}
|
||||
// Push each slide change to the browser history
|
||||
{% if history %}
|
||||
history: {{ history }},
|
||||
{{ else }}
|
||||
history: true,
|
||||
{% endif %}
|
||||
{% if keyboard %}
|
||||
// Enable keyboard shortcuts for navigation
|
||||
keyboard: {{ keyboard }},
|
||||
{% endif %}
|
||||
{% if overview %}
|
||||
// Enable the slide overview mode
|
||||
overview: {{ overview }},
|
||||
{% endif %}
|
||||
{% if center %}
|
||||
// Vertical centering of slides
|
||||
center: {{ center }},
|
||||
{% endif %}
|
||||
{% if touch %}
|
||||
// Enables touch navigation on devices with touch input
|
||||
touch: {{ touch }},
|
||||
{% endif %}
|
||||
{% if loop %}
|
||||
// Loop the presentation
|
||||
loop: {{ loop }},
|
||||
{% endif %}
|
||||
{% if rtl %}
|
||||
// Change the presentation direction to be RTL
|
||||
rtl: {{ rtl }},
|
||||
{% endif %}
|
||||
{% if navigationMode %}
|
||||
// see https://github.com/hakimel/reveal.js/#navigation-mode
|
||||
navigationMode: '{{ navigationMode }}',
|
||||
{% endif %}
|
||||
{% if fragments %}
|
||||
// Turns fragments on and off globally
|
||||
fragments: {{ fragments }},
|
||||
{% endif %}
|
||||
{% if embedded %}
|
||||
// Flags if the presentation is running in an embedded mode,
|
||||
// i.e. contained within a limited portion of the screen
|
||||
embedded: {{ embedded }},
|
||||
{% endif %}
|
||||
{% if help %}
|
||||
// Flags if we should show a help overlay when the questionmark
|
||||
// key is pressed
|
||||
help: {{ help }},
|
||||
{% endif %}
|
||||
{% if showNotes %}
|
||||
// Flags if speaker notes should be visible to all viewers
|
||||
showNotes: {{ showNotes }},
|
||||
{% endif %}
|
||||
{% if autoSlide %}
|
||||
// Number of milliseconds between automatically proceeding to the
|
||||
// next slide, disabled when set to 0, this value can be overwritten
|
||||
// by using a data-autoslide attribute on your slides
|
||||
autoSlide: {{ autoSlide }},
|
||||
{% endif %}
|
||||
{% if autoSlideStoppable %}
|
||||
// Stop auto-sliding after user input
|
||||
autoSlideStoppable: {{ autoSlideStoppable }},
|
||||
{% endif %}
|
||||
{% if mouseWheel %}
|
||||
// Enable slide navigation via mouse wheel
|
||||
mouseWheel: {{ mouseWheel }},
|
||||
{% endif %}
|
||||
{% if rollingLinks %}
|
||||
// Apply a 3D roll to links on hover
|
||||
rollingLinks: {{ rollingLinks }},
|
||||
{% endif %}
|
||||
{% if hideAddressBar %}
|
||||
// Hides the address bar on mobile devices
|
||||
hideAddressBar: {{ hideAddressBar }},
|
||||
{% endif %}
|
||||
{% if previewLinks %}
|
||||
// Opens links in an iframe preview overlay
|
||||
previewLinks: {{ previewLinks }},
|
||||
{% endif %}
|
||||
{% if transition %}
|
||||
// Transition style
|
||||
transition: '{{ transition }}', // none/fade/slide/convex/concave/zoom
|
||||
{% endif %}
|
||||
{% if transitionSpeed %}
|
||||
// Transition speed
|
||||
transitionSpeed: '{{ transitionSpeed }}', // default/fast/slow
|
||||
{% endif %}
|
||||
{% if backgroundTransition %}
|
||||
// Transition style for full page slide backgrounds
|
||||
backgroundTransition: '{{ backgroundTransition }}', // none/fade/slide/convex/concave/zoom
|
||||
{% endif %}
|
||||
{% if viewDistance %}
|
||||
// Number of slides away from the current that are visible
|
||||
viewDistance: {{ viewDistance }},
|
||||
{% endif %}
|
||||
{% if parallaxBackgroundImage %}
|
||||
// Parallax background image
|
||||
parallaxBackgroundImage: '{{ parallaxBackgroundImage }}', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
|
||||
{{ else }}
|
||||
{% if background-image %}
|
||||
// Parallax background image
|
||||
parallaxBackgroundImage: '{{ background_image }}', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if parallaxBackgroundSize %}
|
||||
// Parallax background size
|
||||
parallaxBackgroundSize: '{{ parallaxBackgroundSize }}', // CSS syntax, e.g. "2100px 900px"
|
||||
{% endif %}
|
||||
{% if parallaxBackgroundHorizontal %}
|
||||
// Amount to move parallax background (horizontal and vertical) on slide change
|
||||
// Number, e.g. 100
|
||||
parallaxBackgroundHorizontal: {{ parallaxBackgroundHorizontal }},
|
||||
{% endif %}
|
||||
{% if parallaxBackgroundVertical %}
|
||||
parallaxBackgroundVertical: {{ parallaxBackgroundVertical }},
|
||||
{% endif %}
|
||||
{% if width %}
|
||||
// The "normal" size of the presentation, aspect ratio will be preserved
|
||||
// when the presentation is scaled to fit different resolutions. Can be
|
||||
// specified using percentage units.
|
||||
width: {{ width }},
|
||||
{% endif %}
|
||||
{% if height %}
|
||||
height: {{ height }},
|
||||
{% endif %}
|
||||
{% if margin %}
|
||||
// Factor of the display size that should remain empty around the content
|
||||
margin: {{ margin }},
|
||||
{% endif %}
|
||||
{% if minScale %}
|
||||
// Bounds for smallest/largest possible scale to apply to content
|
||||
minScale: {{ minScale }},
|
||||
{% endif %}
|
||||
{% if maxScale %}
|
||||
maxScale: {{ maxScale }},
|
||||
{% endif %}
|
||||
{% if zoomKey %}
|
||||
// Modifier key used to click-zoom to part of the slide
|
||||
zoomKey: '{{ zoomKey }}',
|
||||
{% endif %}
|
||||
{% if mathjax %}
|
||||
math: {
|
||||
mathjax: '{{ mathjaxurl }}',
|
||||
config: 'TeX-AMS_HTML-full',
|
||||
tex2jax: {
|
||||
inlineMath: [['\\(','\\)']],
|
||||
displayMath: [['\\[','\\]']],
|
||||
balanceBraces: true,
|
||||
processEscapes: false,
|
||||
processRefs: true,
|
||||
processEnvironments: true,
|
||||
preview: 'TeX',
|
||||
skipTags: ['script','noscript','style','textarea','pre','code'],
|
||||
ignoreClass: 'tex2jax_ignore',
|
||||
processClass: 'tex2jax_process'
|
||||
},
|
||||
},
|
||||
{% endif %}
|
||||
|
||||
// Optional reveal.js plugins
|
||||
Reveal.initialize({
|
||||
hash: true,
|
||||
fragments: true,
|
||||
dependencies: [
|
||||
{ src: '{{ revealjs_url }}/plugin/markdown/marked.js', condition: function() { return !!document.querySelector('[data-markdown]'); } },
|
||||
{ src: '{{ revealjs_url }}/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector('[data-markdown]'); } },
|
||||
{ src: '{{ revealjs_url }}/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
|
||||
|
||||
{ src: '{{ revealjs_url }}/lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
||||
{ src: '{{ revealjs_url }}/plugin/zoom-js/zoom.js', async: true },
|
||||
{% if notes_server %}
|
||||
{ src: '{{ revealjs_url }}/socket.io/socket.io.js', async: true },
|
||||
{ src: '{{ revealjs_url }}/plugin/notes-server/client.js', async: true },
|
||||
{% endif %}
|
||||
{% if mathjax %}
|
||||
{ src: '{{ revealjs_url }}/plugin/math/math.js', async: true },
|
||||
{% endif %}
|
||||
{ src: '{{ revealjs_url }}/plugin/notes/notes.js', async: true }
|
||||
]
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user