Complément - niveau basique¶
%load_ext ipythontutorLes opérateurs is et ==¶
nous avons déjà parlé de l’opérateur
==qui compare la valeur de deux objets ;python fournit aussi un opérateur
isqui permet de savoir si deux valeurs correspondent au même objet en mémoire.
Nous allons illustrer la différence entre ces deux opérateurs.
Scénario 1¶
# deux listes identiques
a = [1, 2]
b = [1, 2]
# les deux objets se ressemblent
print('==', a == b)== True
# mais ce ne sont pas les mêmes objets
print('is', a is b)is False
Scénario 2¶
# par contre ici il n'y a qu'une liste
a = [1, 2]
# et les deux variables
# référencent le même objet
b = a
# non seulement les deux expressions se ressemblent
print('==', a == b)== True
# mais elles désignent le même objet
print('is', a is b)is True
La même chose sous pythontutor¶
Scénario 1¶
%%ipythontutor curInstr=2
a = [1, 2]
b = [1, 2]Scénario 2¶
%%ipythontutor curInstr=1
# équivalent à la forme ci-dessus
# a = [1, 2]
# b = a
a = b = [1, 2]Utilisez is plutôt que == lorsque c’est possible¶
La pratique usuelle est d’utiliser is lorsqu’on compare avec un objet qui est un singleton, comme typiquement None.
Par exemple on préfèrera écrire :
undef = None
if undef is None:
print('indéfini')indéfini
Plutôt que :
if undef == None:
print('indéfini')indéfini
Qui se comporte de la même manière (à nouveau, parce qu’on compare avec None), mais est légèrement moins lisible, et franchement moins pythonique. :)
Notez aussi et surtout que is est plus efficace que ==. En effet is peut être évalué en temps constant, puisqu’il s’agit essentiellement de comparer les deux adresses. Alors que pour == il peut s’agir de parcourir toute une structure de données possiblement très complexe.
Complément - niveau intermédiaire¶
La fonction id¶
Pour bien comprendre le fonctionnement de is nous allons voir la fonction id qui retourne un identificateur unique pour chaque objet ; un modèle mental acceptable est celui d’adresse mémoire.
id(True)10654560Comme vous vous en doutez, l’opérateur is peut être décrit formellement à partir de id comme ceci :
(a is b) (id(a) == id(b))
Certains types de base sont des singletons¶
Un singleton est un objet qui n’existe qu’en un seul exemplaire dans la mémoire. Un usage classique des singletons en Python est de minimiser le nombre d’objets immuables en mémoire. Voyons ce que cela nous donne avec des entiers :
a = 3
b = 3
print('a', id(a), 'b', id(b))a 11755752 b 11755752
Tiens, c’est curieux, nous avons ici deux objets, que l’on pourrait penser différents, mais en fait ce sont les mêmes ; a et b désignent le même objet python, et on a :
a is bTrueIl se trouve que, dans le cas des petits entiers, python réalise une optimisation de l’utilisation de la mémoire. Quel que soit le nombre de variables dont la valeur est 3, un seul objet correspondant à l’entier 3 est alloué et créé, pour éviter d’engorger la mémoire. On dit que l’entier 3 est implémenté comme un singleton ; nous reverrons ceci en exercice.
On trouve cette optimisation avec quelques autres objets python, comme par exemple :
a = ""
b = ""
a is bTrueOu encore, plus surprenant :
a = "foo"
b = "foo"
a is bTrueConclusion cette optimisation ne touche aucun type mutable (heureusement) ; pour les types immuables, il n’est pas extrêmement important de savoir en détail quels objets sont implémentés de la sorte.
Ce qui est par contre extrêmement important est de comprendre la différence entre is et ==, et de les utiliser à bon escient au risque d’écrire du code fragile.
Pour en savoir plus¶
Aux étudiants de niveau avancé, nous recommandons la lecture de la section “Objects, values and types” dans la documentation Python :
https://
qui aborde également la notion de “garbage collection”, que nous n’aurons pas le temps d’approfondir dans ce MOOC.