Création dynamique de structures de données
Qu'appelle-t-on "création dynamique de structures de données" ? Il s'agit simplement de permettre de créer directement un dictionnaire de dictionnaire en une seule ligne, comme cela se fait nativement en PHP, par exemple :
$a = array();En PHP, si l'on écrit une telle chose, alors que la première clé n'existe pas, alors le code prévoit de la rajouter automatiquement. Cela tient à la volonté du langage d'être simple à utiliser et de traiter au maximum les erreurs. En Python, les choses ne se passent pas exactement de la même manière, puisque si une clé n'existe pas et que l'on tente de l'utiliser, alors on a une exception. Il n'y a pas de routine permettant de la rajouter automatiquement, c'est au développeur de faire le travail et le langage reste rigoureux. Voici ce qu'il se passe si l'on écrit un équivalent du code précédent en Python :
$a['truc']['machin'] = 42;
>>> d = {}
>>> d['truc']['machin'] = 42
Traceback (most recent call last):
File "", line 1, in
KeyError: 'truc'
Or, une telle fonctionnalité peut, dans des contextes où les structures ne sont pas prédéterminées ou figées serait relativement utile. C'est pourquoi Python la prévoit. Pour cela, il faut commencer par se créer la structure :
>>> from collections import defaultdict
>>> def tree():
... return defaultdict(tree)
...
Ce code extrêmement court fonctionne, car au moment où la fonction est lue, elle existe et est présente dans son propre espace de nommage (ce qui permet également la récursivité).
Voici ce que cela donne :
>>> d=tree()
>>> d['truc']['machin'] = 42
Cela fonctionne donc plutôt correctement. Rajoutons qu'un entier est également un objet hashable donc qui peut être utilisé en tant que clé. On peut donc construire tout type de dictionnaire de dictionnaires.
Voici à quoi ressemble le résultat obtenu :
>>> d
defaultdict(<function tree at 0xee7b78>, {'truc': defaultdict(<function tree at 0xee7b78>, {'machin': 0})})
Python permet la création dynamique de structures en prévoyant un attribut dédié, celui qui est mis à jour dans la construction de l'objet defaultdict. Voici ceci mis en évidence :
>>> d.default_factory
<function tree at 0xee7b78>
Voici à quoi ressemble la structure ainsi obtenue :
>>> list(d.items())
[('truc', defaultdict(<function tree at 0xee7b78>, {'machin': 0}))]
>>> len(list(d.items()))
1
Voici donc une technique intéressante à rajouter à votre catalogue si ce n'est pas encore fait.