De la bonne utilisation du test ‘is’ en python


Python est avare en mémoire: s’il peut utiliser le même objet deux fois il le fait:

>>> _MARKER = 'XXX'
>>>
>>> a = 'XXX'
>>> a is _MARKER
True
>>> a = a[:] # force la copie
>>> a is _MARKER
True
>>> a = a + 'X'
>>> a is _MARKER
False

>>> b = _MARKER
>>> b is _MARKER
True
>>> b = b + 'X'
>>> b is _MARKER
False

Lorsque deux chaines de caractères sont identiques python utilise la même référence en mémoire s’il considère que cela est pertinent, mais pas toujours. Dans le cas des tests a et b il a fallu modifier la valeur des variables pour changer de références.

Conclusion: utiliser ‘is’ sur des chaines de caractère est une source de bug. Il vaut mieux utiliser ‘==’ qui est plus adapté.

Maintenant, le cas des listes (mais pas des tuples):

>>> _MARKER2 = ['1', '2']
>>> c = _MARKER2

>>> c is _MARKER2
True

>>> c.append(3)
>>> c is _MARKER2
True

>>> c == _MARKER2
True

>>> _MARKER2
['1', '2', 3]

La variable c, via l’affection initiale, partage la même référence que le marqueur. Modifier la variable revient à modifier le marqueur.

Aller, la victoire sur les néo-zélandais mérite un petit mal de crane:

>>> from copy import copy
>>> d = copy(_MARKER2)

>>> d is _MARKER2
False

>>> d == _MARKER2
True

Que se passe-t-il ?

  1. ‘is’ vérifie les pointeurs et l’utilisation de ‘copy’ nous assure qu’ils sont différents.
  2. ‘==’ vérifie les valeurs et l’utilisation de ‘copy’, ou de deepcopy dans les cas les plus complexes, nous assure qu’elles sont identiques.
>>> d.append(4)

>>> d is _MARKER2
False

>>> d == _MARKER2
False

La variable d est bien indépendante du marqueur.

Conclusion générale:

La question de l’utilisation de ‘is’ est un grand classique de python et pour faire simple il ne faut pas l’utiliser sauf lorsque l’on veut s’assurer que deux objets utilisent la même référence. Dans la plupart des tests c’est la valeur contenu dans la variable que nous souhaitons tester et c’est l’opérateur ‘==’ qu’il faut impérativement utiliser dans ce cas.
L’implémentation de la gestion des chaines de caractères dans python peut perturber ‘is’. Il ne faut pas l’utiliser avec sous peine d’avoir des bugs assez pénibles à trouver.

Le cas le plus fréquent de l’utilisation de ‘is’ est la vérification d’une valeur passée en argument d’une fonction ou d’une méthode.

Les commentaires sont fermés.

%d blogueurs aiment cette page :