194 lines
6.1 KiB
Markdown
194 lines
6.1 KiB
Markdown
---
|
||
title: Documenter du code Python
|
||
author: Steve Kossouho
|
||
---
|
||
|
||
# Documenter du code Python
|
||
|
||
----
|
||
|
||
## Documenter du code ?
|
||
|
||
En Python, comme dans d'autres langages, vous savez que l'on peut introduire des commentaires dans le code.
|
||
Il suffit d'utiliser le symbole `(#)` dans une ligne de code, et ce qui suit sera considéré comme commentaire.
|
||
|
||
Mais saviez-vous que Python considère le concept de documentation comme étant à part ?
|
||
|
||
----
|
||
|
||
```python {.numberLines}
|
||
print(__doc__) # Ne provoque pas d'erreur, mais affiche `None`
|
||
```
|
||
|
||
Les modules, packages, classes, fonctions et méthodes sont toujours, lorsque vous exécutez l'interpréteur Python,
|
||
équipés d'attributs nommés `__doc__`. (C'est l'interpréteur qui ajoute l'attribut automatiquement, entre autres
|
||
fonctionnements magiques)
|
||
Tout module possède implicitement une variable `__doc__` disponible dans son namespace/scope.
|
||
Cet attribut « magique » laisse entendre que la notion de documentation fait partie intégrante du langage Python.
|
||
|
||
----
|
||
|
||
### Documentation dans la bibliothèque standard
|
||
|
||
```python {.numberLines}
|
||
import sqlite3
|
||
|
||
print(sqlite3.__doc__) # documentation du module SQLite3
|
||
```
|
||
|
||
Ici, on importe un module écrit par un développeur tiers, pour voir si l'on est capable de
|
||
récupérer quelque chose dans son attribut `__doc__`{.python}.
|
||
|
||
----
|
||
|
||
## Comment on fait pareil qu'eux ?
|
||
|
||
Pour documenter un module, c'est finalement assez simple :
|
||
|
||
```python {.numberLines}
|
||
"""Texte de documentation du module."""
|
||
import os, sys
|
||
print(os.linesep, sys.getwindowsversion())
|
||
```
|
||
|
||
Il faut, en première instruction du module, écrire une chaîne de caractères. Par convention, il faut écrire une chaîne à trois guillemets. En Python, on appelle cela une docstring. (consultez PEP8 docstrings)
|
||
|
||
----
|
||
|
||
## Qu'est-ce qu'on peut documenter ?
|
||
|
||
On peut documenter pas mal de choses avec cette méthode :
|
||
|
||
1. Modules et packages;
|
||
2. fonctions et méthodes;
|
||
3. classes.
|
||
|
||
Les variables ne sont pas documentables directement : elles
|
||
récupèrent automatiquement la **documentation de leur classe**.
|
||
|
||
----
|
||
|
||
## Qu'est-ce qu'on met ?
|
||
|
||
Pour documenter, par exemple, un module, il y a deux façons de faire :
|
||
|
||
1. Si votre documentation tient en une phrase courte.
|
||
2. Si votre documentation va contenir davantage de texte.
|
||
|
||
----
|
||
|
||
### Documentation super courte
|
||
|
||
Vous pouvez considérer qu'une seule petite phrase peut servir à décrire votre module :
|
||
|
||
```python {.numberLines}
|
||
"""Traitement des données d'épuration des eaux."""
|
||
```
|
||
|
||
----
|
||
|
||
### Documentation plus longue
|
||
|
||
```python {.numberLines}
|
||
"""
|
||
Traitement des données d'épuration des eaux.
|
||
|
||
Paragraphes de description, d'explication du contenu du module.
|
||
Possibilité d'ajouter des sections, des exemples, soyez exhaustifs si vous le souhaitez !
|
||
"""
|
||
```
|
||
|
||
- Une phrase courte de résumé, sur sa propre ligne.
|
||
- Une ligne vide.
|
||
- Le corps de la documentation.
|
||
|
||
----
|
||
|
||
## Documenter une classe, fonction, méthode, package
|
||
|
||
- Pour documenter une classe, il suffit d'ajouter une docstring, juste en-dessous de la signature de la classe.
|
||
- Pour une fonction, ajoutez vos triples guillemets en-dessous de la signature de méthode/fonction.
|
||
- Pour un package, mettez une docstring au sommet du module `__init__.py`
|
||
|
||
----
|
||
|
||
## Outils de génération de documentation HTML etc.
|
||
|
||
Mieux qu'un long discours, une démo s'impose, avec la bibliothèque `pdoc`.
|
||
Un outil beaucoup plus long à mettre en place est `sphinx`, qui permet encore davantage.
|
||
|
||
```bash {.numberLines}
|
||
pip install pdoc # installer la bibliothèque
|
||
pdoc [nom du module ou nom du script python] # lance un serveur pour tester
|
||
```
|
||
|
||
- [Documentation de pdoc](https://pdoc.dev/docs/pdoc.html)
|
||
- [Documentation de Sphinx](https://www.sphinx-doc.org/en/master/)
|
||
|
||
----
|
||
|
||
## Bonus : Donner des indications sur le type des variables et arguments
|
||
|
||
Depuis Python 3.5 (fin 2015), le langage propose un moyen d'indiquer aux développeurs, le type attendu de variables et d'arguments de fonctions.
|
||
|
||
**Attention cependant** : les indications en question n'ont aucune incidence sur l'exécution du code, c'est-à-dire que l'interpréteur les ignore. Par contre, les développeurs et les environnements de développement, eux, peuvent se servir de ces indications pour proposer de l'autocomplétion dans certains cas.
|
||
|
||
----
|
||
|
||
Pour annoter une variable et définir quel est son type attendu, on peut :
|
||
|
||
```python {.numberLines}
|
||
from tartempion import MyClass
|
||
|
||
variable1: int = 15 # on indique qu'on attend un entier
|
||
variable2: str = "Hello" # on attend une chaîne
|
||
variable3: list = [] # on attend une liste
|
||
object1: MyClass = MyClass() # on attend un objet d'une classe
|
||
```
|
||
|
||
Un éditeur (tel que PyCharm) ou un outil de vérification en ligne de commande saura vous dire
|
||
si ailleurs dans votre code, vous ne respectez pas ces indications.
|
||
|
||
----
|
||
|
||
Le module `typing` de la bibliothèque standard permet de décrire de façon plus avancée des types attendus :
|
||
|
||
```python {.numberLines}
|
||
from typing import Optional, Union, Any, Literal, Callable
|
||
|
||
variable: Optional[int] = None # on attend `None` ou un entier
|
||
multi_types: Union[int, float] = 25 # on attend un entier ou float
|
||
collection: list[str] = [] # ne fonctionne que dans Python 3.9+
|
||
shapeshifter: Any = [] # tout et n'importe quoi, explicitement
|
||
finite_values: Literal["Monday", "Tuesday"] = "Monday" # Valeurs finies
|
||
function_reference: Callable = range # on attend une fonction
|
||
```
|
||
|
||
À partir de Python 3.11 (novembre 2022), il est possible de remplacer l'`Union` par un opérateur `|` :
|
||
|
||
```python {.numberLines}
|
||
variable: int | float = 15 # soit un entier soit un flottant devrait y être associé
|
||
```
|
||
|
||
[Section de la documentation officielle de Typing](https://docs.python.org/3/library/typing.html#module-contents)
|
||
|
||
----
|
||
|
||
On peut faire la même chose avec des arguments de fonctions :
|
||
|
||
```python {.numberLines}
|
||
# value et default devraient être des entiers
|
||
def do_some_important_things(value: int, default: int = 1):
|
||
print(value, default)
|
||
return None
|
||
```
|
||
|
||
----
|
||
|
||
Et on peut également décrire le type attendu du retour des fonctions et méthodes :
|
||
|
||
```python {.numberLines}
|
||
def do_trivial_things() -> float: # on indique que la fonction retourne un flottant
|
||
return 100 / 15
|
||
```
|