|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Salvatore a écrit :
> Bonjour la communauté, > > Voici un petit bout de code qui m'intrigue, > > > >>> v = 'TEST' > >>> if not v is 'TEST': if v is not 'TEST' aurais été plus lisible AMHA. Ceci étant dit, l'opérateur 'is' sert à tester l'identité de deux objets, et non leur égalité. C'est en fait le strict équivalent de : if id(v) != id('TEST') Et ce n'est en aucun cas l'opérateur qui convient pour la comparaison que tu fais ici. Si tu veux tester une égalité de valeur, utilise l'opérateur '=='. Pour info, voici deux ou trois cas d'utilisation correcte de 'is': a = 'TEST' b = a print a is b c = None print c is None: def toto(): pass d = toto print d is toto etc... Comme tu peux le constater, dans aucun de ces cas on ne teste contre un litéral. (snip) > 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 Manifestement, ta conclusion est (au moins partiellement) erronée. La présence du slash ne modifie en rien le comportement de 'is', bien qu'elle puisse modifier le résultat de ton test. > Curieusement, je n'avais encore jamais été confronté à cette situation. > Si quelqu'un a une explication, je suis preneur Détail d'implémentation de CPython, qui tente autant que possible de cacher certains objets immutables. Tu aurais pu avoir une surprise similaire avec des entiers: >>> a = 1 >>> print a is 1 True >>> b = 1024*1024 >>> print b is 1024*1024 False >>> ou des expressions booléennes: >>> print a == 1 True >>> print (a == 1) is True True >>> print a == 1 is True False >>> Bref, et pour résumer : utilise '==' pour une égalité de valeur, et 'is' pour des identités d'objets. HTH |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Salvatore a écrit :
> Bonjour la communauté, > > Voici un petit bout de code qui m'intrigue, > > > >>> v = 'TEST' > >>> if not v is 'TEST': if v is not 'TEST' aurais été plus lisible AMHA. Ceci étant dit, l'opérateur 'is' sert à tester l'identité de deux objets, et non leur égalité. C'est en fait le strict équivalent de : if id(v) != id('TEST') Et ce n'est en aucun cas l'opérateur qui convient pour la comparaison que tu fais ici. Si tu veux tester une égalité de valeur, utilise l'opérateur '=='. Pour info, voici deux ou trois cas d'utilisation correcte de 'is': a = 'TEST' b = a print a is b c = None print c is None: def toto(): pass d = toto print d is toto etc... Comme tu peux le constater, dans aucun de ces cas on ne teste contre un litéral. (snip) > 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 Manifestement, ta conclusion est (au moins partiellement) erronée. La présence du slash ne modifie en rien le comportement de 'is', bien qu'elle puisse modifier le résultat de ton test. > Curieusement, je n'avais encore jamais été confronté à cette situation. > Si quelqu'un a une explication, je suis preneur Détail d'implémentation de CPython, qui tente autant que possible de cacher certains objets immutables. Tu aurais pu avoir une surprise similaire avec des entiers: >>> a = 1 >>> print a is 1 True >>> b = 1024*1024 >>> print b is 1024*1024 False >>> ou des expressions booléennes: >>> print a == 1 True >>> print (a == 1) is True True >>> print a == 1 is True False >>> Bref, et pour résumer : utilise '==' pour une égalité de valeur, et 'is' pour des identités d'objets. HTH |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Christophe Cavalaria a écrit :
(snip) > is, c'est l'operateur d'égalité d'objet en mémoire. (repost suite à erreur - Christophe, tu a probablement recu la réponse en privé, si oui mes excuses pour la fausse manip) 'is' est l'opérateur de comparaison d'identité. C'est à dire que : a is b est strictement équivalent à: id(a) == id(b) (se référer à la définition de id()) Le fait que CPython utilise l'adresse mémoire comme identifiant unique d'un objet, bien qu'évident d'un point de vue pratique, n'est qu'un détail d'implémentation. Et avant que quelqu'un ne le dise, oui, je sais, je suis puriste et pédant !-) |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
Christophe Cavalaria a écrit :
(snip) > is, c'est l'operateur d'égalité d'objet en mémoire. (repost suite à erreur - Christophe, tu a probablement recu la réponse en privé, si oui mes excuses pour la fausse manip) 'is' est l'opérateur de comparaison d'identité. C'est à dire que : a is b est strictement équivalent à: id(a) == id(b) (se référer à la définition de id()) Le fait que CPython utilise l'adresse mémoire comme identifiant unique d'un objet, bien qu'évident d'un point de vue pratique, n'est qu'un détail d'implémentation. Et avant que quelqu'un ne le dise, oui, je sais, je suis puriste et pédant !-) |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
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 Cordialement Salvatore |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Bonsoir !
Je n'obtiens pas les mêmes résultats que toi. -- @-salutations Michel Claveau |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Bonsoir !
Je n'obtiens pas les mêmes résultats que toi. -- @-salutations Michel Claveau |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
On 05-10-2007, MC wrote:
> Bonsoir ! > > Je n'obtiens pas les mêmes résultats que toi. moi si In [1]: v='N/A' In [2]: v is 'N/A' Out[2]: False In [3]: v='TEST' In [4]: v is 'TEST' Out[4]: True curieusement le '/' seul ne pose pas de problème In [10]: v='/' In [11]: v is '/' Out[11]: True j'ai pas d'explication... -- William Dodé - http://flibuste.net Informaticien indépendant |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
On 05-10-2007, MC wrote:
> Bonsoir ! > > Je n'obtiens pas les mêmes résultats que toi. moi si In [1]: v='N/A' In [2]: v is 'N/A' Out[2]: False In [3]: v='TEST' In [4]: v is 'TEST' Out[4]: True curieusement le '/' seul ne pose pas de problème In [10]: v='/' In [11]: v is '/' Out[11]: True j'ai pas d'explication... -- William Dodé - http://flibuste.net Informaticien indépendant |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
Salvatore wrote:
> 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 > > Cordialement > > Salvatore is, c'est l'operateur d'égalité d'objet en mémoire. Il est tout à fait envisageable d'avoir en deux string différentes en mémoire ayant le même contenu. A ce moment, les strings comparent à faux avec is mais à vrai avec == car ce dernier test le contenu des objets a is b <=> id(a) == id(b) Après, la ligne de commande python ou le compilateur .py=>.pyc peut faire certaines optimisations qui fait que ce genre de code renvoit vrai sur le premier print : >>> a = "test" >>> b = "test" >>> print a is b >>> a += "e" >>> b += "e" >>> print a is b Mais en général, vous obtenez toujours faux sur le deuxième même si manifestement a == b. |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
Salvatore wrote:
> 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 > > Cordialement > > Salvatore is, c'est l'operateur d'égalité d'objet en mémoire. Il est tout à fait envisageable d'avoir en deux string différentes en mémoire ayant le même contenu. A ce moment, les strings comparent à faux avec is mais à vrai avec == car ce dernier test le contenu des objets a is b <=> id(a) == id(b) Après, la ligne de commande python ou le compilateur .py=>.pyc peut faire certaines optimisations qui fait que ce genre de code renvoit vrai sur le premier print : >>> a = "test" >>> b = "test" >>> print a is b >>> a += "e" >>> b += "e" >>> print a is b Mais en général, vous obtenez toujours faux sur le deuxième même si manifestement a == b. |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
Christophe Cavalaria a écrit :
> Salvatore wrote: > > Mais en général, vous obtenez toujours faux sur le deuxième même si > manifestement a == b. Merci pour cette explication, Christophe. Il faut en conclure que pour tester le 'contenu' d'une variable il faut sytématiquement utiliser l'opérateur '==' et non l'opérateur 'is', qui lui est réservé pour tester l'identité de 2 objets. |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
Christophe Cavalaria a écrit :
> Salvatore wrote: > > Mais en général, vous obtenez toujours faux sur le deuxième même si > manifestement a == b. Merci pour cette explication, Christophe. Il faut en conclure que pour tester le 'contenu' d'une variable il faut sytématiquement utiliser l'opérateur '==' et non l'opérateur 'is', qui lui est réservé pour tester l'identité de 2 objets. |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
William Dode a écrit :
> curieusement le '/' seul ne pose pas de problème > In [10]: v='/' > > In [11]: v is '/' > Out[11]: True >>> a = '/' >>> a is '/' False Décidément notre ami Python nous joue des tours :-) |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
William Dode a écrit :
> curieusement le '/' seul ne pose pas de problème > In [10]: v='/' > > In [11]: v is '/' > Out[11]: True >>> a = '/' >>> a is '/' False Décidément notre ami Python nous joue des tours :-) |
|
|
|
#16 |
|
Messages: n/a
Hébergeur: |
Bruno Desthuilliers a écrit :
> Bref, et pour résumer : utilise '==' pour une égalité de valeur, et 'is' > pour des identités d'objets. > > HTH Entièrement d'accord Bruno :-) Merci |
|
|
|
#17 |
|
Messages: n/a
Hébergeur: |
Bruno Desthuilliers a écrit :
> Bref, et pour résumer : utilise '==' pour une égalité de valeur, et 'is' > pour des identités d'objets. > > HTH Entièrement d'accord Bruno :-) Merci |
|
|
|
#18 |
|
Messages: n/a
Hébergeur: |
> Et avant que quelqu'un ne le dise, oui, je sais, je suis puriste et
> pédant !-) Aucune importance ! ...sans préjuger du fait éventuel que ce soit vrai ;-) |
|
|
|
#19 |
|
Messages: n/a
Hébergeur: |
> Et avant que quelqu'un ne le dise, oui, je sais, je suis puriste et
> pédant !-) Aucune importance ! ...sans préjuger du fait éventuel que ce soit vrai ;-) |
|
|
|
#20 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#21 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#22 |
|
Messages: n/a
Hébergeur: |
On 07-10-2007, Encolpe Degoute wrote:
> 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: N'empêche qu'il serait intéressant de savoir pourquoi dans un cas il le fait et pas dans un autre... Je pensais qu'en cpython c'était systématique. -- William Dodé - http://flibuste.net Informaticien indépendant |
|
|
|
#23 |
|
Messages: n/a
Hébergeur: |
On 07-10-2007, Encolpe Degoute wrote:
> 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: N'empêche qu'il serait intéressant de savoir pourquoi dans un cas il le fait et pas dans un autre... Je pensais qu'en cpython c'était systématique. -- William Dodé - http://flibuste.net Informaticien indépendant |
|
|
|
#24 |
|
Messages: n/a
Hébergeur: |
Merci pour cette explication Encolpe :-)
|
|
|
|
#25 |
|
Messages: n/a
Hébergeur: |
Merci pour cette explication Encolpe :-)
|
|
![]() |
| Outils de la discussion | |
|
|