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