Contenu

Les objets mutables et immuables en python

Les objets mutables et immuables en python. (Mutable ou immutable en anglais)

1 Définitions et exemples

Définition simple : Un objet immuable est un objet qui ne peut pas être modifié après sa création.

Les objets immuables en python : int, float, bool, string, tuple

Un objet mutables est un objet dont on peut changer les propriétés après la création.

Exemples d’objets mutables en python: list, dict, set

2 Application

Objet mutable

Immuable n’empêche pas de modifier la valeur.

En programmation et surtout avec python on peut faire l’erreur de confondre réassignation et modification.

Mais une variable n’est pas un espace alloué dans la mémoire.

Une variable est simplement une étiquette qui pointe sur un objet stocké en mémoire, la différence est subtile mais importante.

Par conséquent il peut y avoir plusieurs noms (ou étiquettes) qui pointent sur la même valeur.

1
2
3
4
5
ma_liste = [1,2,3,4]
mon_autre_liste = ma_liste
ma_liste.append(5)
ma_liste # [1,2,3,4,5]
mon_autre_liste # [1,2,3,4,5]

Dans l’exemple précédent les deux noms de variable : ma_liste et mon_autre_liste pointent sur le même objet qui est mutable ainsi la valeur des deux variables changent lorsque l’on modifie la valeur d’une seule variable.

Si vous modifiez un objet mutable sachez que toute les variables qui pointent vers cet objet seront modifiées de la même manière.

Comment fonctionne une réaffectation pour une variable pointant vers un objet immuable:

Si j’ai une chaine de caractère :

1] a = "bonjour"

Je peux très bien changer sa valeur, et dire :

2] a = "Hola"

Cette réafectation ne modifie pas la valeur de l’objet « String » original mais crée une copie dans la mémoire.

Toute modification d’une variable contenant un objet immuable implique alors la création d’une copie.

Cependant si je fais:

3] c = "Hola"

Python est assez intelligent pour trouver un objet en mémoire qui a la même valeur, il va alors faire pointer c sur le même objet que a.

/les-objets-mutables-et-immuable/mutable1.drawio.png
Illustration des 3 cas précédents

Mais qu’adviendra-t-il de l’ancien “bonjour” ?

Il sera supprimé par le garbage collector.

Le fonctionnement du garbage collector sera expliqué dans un prochain article

3 Comment python fait la distinction ?

Prouvons maintenant qu’un objet de type < Integer > est immuable:

Avec la fonction id() on va contrôler l’identité de nos variables et non leur égalité.

L’identité est l’identificateur unique de l’objet. Ainsi il ne peut pas y avoir deux objets différent avec le même id en mémoire.

Testons l’utilisation de la fonction id() qui est intégrée avec python et qui permet de connaître l’adresse mémoire de l’objet que l’on passe en argument de la fonction.

Remarque
Le type int est un type primitif qui est crée à partir d’un objet de type , tout est objet en python !

Dans l’exemple suivant les adresses mémoires sont différentes, on en déduit qu’un nouvel objet a été crée.

1
2
3
4
mon_nombre = 150
id(mon_nombre) #140337077949328
mon_nombre = 35
id(mon_nombre) #140337077945648
Astuces

Deux objets sont égaux lorsqu’ils ont le même état.

En effet il y a une méthode __equal__() dans chaque objet qui permet de tester l’égalité avec un autre objet.

Deux objets sont égaux selon l’implementation de cette méthode equal.

Pour en déduire que les objets sont égaux, la méthode vérifie que les attributs des deux objets sont égaux.

Deux chaines de caractères sont égales lorsqu’elles contiennent les mêmes caractères et dans le même ordre.

Pour les chaînes de caractères c’est la méhode equal de l’objet String qui se charge de la comparaison.

On teste cette égalité avec l’opérateur ==.

Cependant deux valeurs sont identiques lorsqu’elles ont la même identité (la valeur de la fonction id()).

Ce qui signifie que les deux variables ont la même instance et qu’elles pointent vers le même objet en mémoire.

4 Problèmes lorsque l’on ne distingue pas les objets mutables et immuables

Pourquoi faire la distinction est important ?

Le code suivant pourrait être écrit par beaucoup de développeurs.

Pour créer la chaine de caractère “1, 2, 3, 4, …” jusqu’à 1000 nous pouvons faire:

1
2
3
4
s = ""
for i in range(1, 1000):
    s += str(i) # Une nouvel objet "String"
    s += "," # Encore un nouvel objet "String"

Combien de nouvelles adresses mémoires vous créez dans ce cas ?

Spoiler alert: 2000 au total !

Aucun problème avec la puissance de nos processeurs.

Mais python a inventé le concept de list comprehension qui permet d’optimiser ce code ça serait dommage de ne pas l’utiliser.

Le concept de compréhension de liste sera détaillé dans un prochain article.

Une autre solution serait de créer une liste de <String> et d’assembler cette liste en une chaîne de caractères avec la méthode .join()

5 Pourquoi utilise-t-on des objets immuables ?

Comme vu précédemment, l’utilisation d’un objet immuable est contraignant au niveau de la mémoire lorsque l’on souhaite faire de nombreuses modifications sur une variable.

Cependant ces objets immuables sont très utilisés et servent à stocker des chaînes de caractères, des entiers, des booléens.

Ils ont l’avantage d’être bien plus rapides que les objets mutables en accès !

Remarque

Attention cas particulier !

Un objet de type <Set> est immuable mais il peut contenir des objets mutables.

Exemple:

1
2
3
4
var_tuple = ("pythonista", [])
#var_tuple.append(4) # Impossible les tuples n'ont pas de méthode add ou extend
var_tuple[1].append(1) # OK
print(var_tuple) # ('pythonista', [1, 1])

Pour résumer:

  • Utiliser un objet mutable lorsqu’il faut modifier la taille ou le contenu de l’objet.
  • Lors la modification d’un objet mutable, toutes les variables qui pointent sur cet objet sont modifiées.
  • Ne pas construire une chaîne de caractère avec une concaténation de <String> (Objet immuable).