This commit is contained in:
Julien Palard 2020-02-25 21:05:20 +01:00
parent 069c1edb43
commit 8d2bba04e3
5 changed files with 332 additions and 251 deletions

View File

@ -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
View 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
View 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

View File

@ -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

View File

@ -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 }
]
});