Mutable et immutable

Auteurs :
  • François Brucker
  • Pierre Brucker

Les 5 type d'objets de base (int, float, complex, bool et str) sont non modifiables (python dira non mutables). Ceci signifie que les méthodes et opérations sur ces objets ne peuvent les modifier :

Les listes, ensembles et dictionnaires sont eux modifiables (python dira mutables), c'est à dire que leurs méthodes peuvent les modifier :

Il est crucial de comprendre cela car les variables ne sont que des associations à des objets, et plusieurs variables différentes peuvent être associée à un même objet. Vérifions cela avec la fonction id.

Si on crée deux listes, elles seront différentes, donc leur id le sera aussi, même si leur contenu est identique :

>>> x = [1, 2]
>>> y = [1, 2]
>>> id(x)
4381752640
>>> id(y)
4381751744

L'id sera certainement différent chez vous, mais les deux id seront différents.

En revanche, associer une liste à une variable ne change pas la liste :

>>> x = [1, 2]
>>> id(x)
4381803264
>>> y = x
>>> id(y)
4381803264

L'id sera certainement différent chez vous, mais il sera identique. Les variables x et y sont associées à la même liste :

>>> x.append('?')
>>> print(x)
[1, 2, '?']
>>> print(y)
[1, 2, '?']

En conclusion, il faut faire très attention lorsque l'on passe des listes en paramètres de fonction.

Si vous jouez avec la fonction id vous serez certainement surpris de constater que :

>>> x = 1
>>> y = 1
>>> id(x)
4378755312
>>> id(y)
4378755312

Ceci est une optimisation de l'interpréteur python. Comme les entiers sont non modifiables, on peut associer le même entier à plusieurs variables sans soucis.

La remarque précédente montre tout l'intérêt d'utiliser des objets non mutables. Il 'y aura jamais d'effet de bords lors de passage de paramètres. En revanche, à chaque modification, il faudra recréer un objet, ce qui peut être long. C'est un compromis à avoir : la sécurité vs la rapidité. C'est pourquoi par défaut :

Il existe des objets non modifiable pouvant être utilisé à la place des listes et des ensembles :

Il n'existe pas d'équivalent non mutable aux dictionnaires.

On peut alors utiliser des tuples et des frozenset comme éléments d'un ensemble ou comme clé de dictionnaires.

Par exemple l'ensemble de tous les sous-ensemble de ${1, 2}$ s'écrira :

>>> x = {frozenset(), frozenset([1]), frozenset([2]), frozenset([1, 2])}
>>> x
{frozenset(), frozenset({2}), frozenset({1}), frozenset({1, 2})}

Le tuple vide s'écrira (,) (ou tuple()) pour la différentier la notation () qui est la parenthèse vide.