Récemment, tout en débogant un morceau de code Python à la plateforme, nous sommes tombés sur une particularité du langage Python.

Prenons cette fonction comme exemple :

def foo(bar=[]):     
    bar.append('a')
    return bar

Intuitivement, ce morceau de code peut sembler retourner la liste ['a'] à chaque appel de la fonction foo(). Mais ce n’est pas le cas:

>>>foo()
['a']
>>>foo()
['a','a']
>>>foo()
['a','a','a']

Comme nous pouvons le constater, la liste n’est pas réinitialisée mais conserve plutôt ses valeurs auxquelles on ajoute un « a » à chaque exécution . Ce comportement est lié à la manière dont Python gère ces fonctions. Les fonctions en Python sont initialisées en tant qu’objet. Les fonctions, ainsi que leurs paramètres, sont donc évaluées lorsqu’elles sont définies et non lorsqu’elles sont exécutées.

Noter que cette particularité ne s’applique pas simplement aux listes. Tous les paramètres de type « mutable » dont les dictionnaires, sets, listes, byte arrays et même les fonctions elles-mêmes auront ce comportement.

J’avoue avoir été surpris de n’être jamais tombé sur ceci bien que cette particularité soit mentionnée comme une erreur fréquente en Python. Il est possible que mon habitude d’initialiser les paramètres par défaut vides à None (plutôt que d’utiliser une liste vide par exemple) m’ait éviter de me trouver dans une situation semblable.