Afficher un message
Vieux 07/10/2007, 15h39   #20
Encolpe Degoute
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: De la mauvaise utilisation de 'is' et '==' ...

Salvatore a écrit :
> Bonjour la communauté,
>
> Voici un petit bout de code qui m'intrigue,
>
>
>>>> v = 'TEST'
>>>> if not v is 'TEST':

> .... print "v est different de 'TEST'"
> .... else:
> .... print "v est egal a 'TEST'"
> ....
> v est egal a 'TEST'
>>>>
>>>>

>
>
>>>> v = 'N/A'
>>>> if not v is 'N/A':

> .... print "v est different de 'N/A'"
> .... else:
> .... print "v est egal a 'N/A'"
> ....
> v est different de 'N/A'
>>>>
>>>> v != 'N/A'

> False
>
>
> J'avoue que je ne comprend pas très bien le fonctionnement de
> l'opérateur 'is' dans ces tests.
> Manifestement le caractère '/' modifie son comportement
> Curieusement, je n'avais encore jamais été confronté à cette situation.
> Si quelqu'un a une explication, je suis preneur


Pour faire un équivalence au C, 'is' vérifie une référence.
Mais python est avare en mémoire: s'il peu 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 ?
'is' vérifie les pointeurs et l'utilisation de 'copy' nous assure qu'ils
sont différents.
'==' 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.
Le cas le plus fréquent de l'utilisation de 'is' est la vérification
d'une valeur passée en argument d'un fonction ou d'un méthode.


Amicalement,
--
Encolpe DEGOUTE
http://encolpe.degoute.free.fr/
Logiciels libres, hockey sur glace et autres activités cérébrales
  Réponse avec citation
 
Page generated in 0,06523 seconds with 9 queries