web-dev-qa-db-fra.com

Comment le mot clé 'is' est-il implémenté en Python?

... le mot clé is qui peut être utilisé pour l'égalité dans les chaînes.

>>> s = 'str'
>>> s is 'str'
True
>>> s is 'st'
False

J'ai essayé à la fois __is__() et __eq__() mais ils ne fonctionnaient pas.

>>> class MyString:
...   def __init__(self):
...     self.s = 'string'
...   def __is__(self, s):
...     return self.s == s
...
>>>
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work
False
>>>
>>> class MyString:
...   def __init__(self):
...     self.s = 'string'
...   def __eq__(self, s):
...     return self.s == s
...
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work, but again failed
False
>>>
58
Srikanth

Tester des chaînes avec is ne fonctionne que lorsque les chaînes sont internées. Sauf si vous savez vraiment ce que vous faites et explicitement interned les chaînes, vous devriez ne jamais utiliser utiliser is sur des chaînes. 

is teste pour identité, pas égalité. Cela signifie que Python compare simplement l'adresse mémoire dans laquelle un objet réside. is répond essentiellement à la question "Ai-je deux noms pour le même objet?" - une surcharge qui n'aurait aucun sens.

Par exemple, ("a" * 100) is ("a" * 100) est False. Habituellement, Python écrit chaque chaîne dans un emplacement de mémoire différent, l'internation se produisant principalement pour les littéraux de chaîne.

119
Jochen Ritzel

L'opérateur is équivaut à comparer les valeurs de id(x). id est actuellement implémenté pour utiliser les pointeurs comme comparaison. Donc, vous ne pouvez pas surcharger is lui-même, et autant que je sache, vous ne pouvez pas surcharger id non plus.

Donc, vous ne pouvez pas. Inhabituel en python, mais le voilà.

18
Phil H

Le mot clé Python is teste l'identité de l'objet. Vous ne devez PAS l'utiliser pour tester l'égalité des chaînes. Cela peut sembler fonctionner fréquemment car les implémentations Python, comme celles de nombreux langages de très haut niveau, effectuent un "interning" de chaînes. Cela signifie que les littéraux de chaîne et les valeurs sont conservés de manière interne dans une liste hachée et que ceux qui sont identiques sont rendus en tant que références au même objet. (Cela est possible car les chaînes Python sont immuables).

Cependant, comme pour tout détail de mise en œuvre, vous ne devez pas vous fier à cela. Si vous voulez tester l'égalité, utilisez l'opérateur ==. Si vous voulez vraiment tester l'identité d'objet, utilisez is --- et j'aurais bien du mal à trouver un cas où vous devriez vous soucier de l'identité de l'objet string. Malheureusement, vous ne pouvez pas compter sur le fait que deux chaînes sont en quelque sorte "intentionnellement" des références d'objet identiques en raison de l'internement susmentionné.

14
Jim Dennis

Le mot clé is compare les objets (ou plutôt, si deux références se rapportent au même objet).

C'est pourquoi, je pense, il n'y a pas de mécanisme pour fournir votre propre implémentation.

Cela arrive parfois de travailler sur des chaînes, car Python stocke les chaînes de manière "intelligente", de sorte que lorsque vous créez deux chaînes identiques, elles sont stockées dans un seul objet.

>>> a = "string"
>>> b = "string"
>>> a is b
True
>>> c = "str"+"ing"
>>> a is c
True

Vous pouvez voir la comparaison référence/données dans un exemple simple de "copie":

>>> a = {"a":1}
>>> b = a
>>> c = a.copy()
>>> a is b
True
>>> a is c
False
8
pycruft

Si vous n'avez pas peur de vous embrouiller avec le bytecode, vous pouvez intercepter et corriger COMPARE_OP avec l'argument 8 ("is") pour appeler votre fonction de raccordement sur les objets comparés. Consultez la documentation du module dis pour le démarrage.

Et n'oubliez pas d'intercepter aussi __builtin__.id() si quelqu'un va faire id(a) == id(b) au lieu de a is b.

5
toriningen

impossible de comparer une variable de chaîne à une valeur de chaîne et à deux variables de chaîne lorsque la chaîne commence par '-'. Ma version Python est 2.6.6

>>> s = '-hi'
>>> s is '-hi'
False 
>>> s = '-hi'
>>> k = '-hi'
>>> s is k 
False
>>> '-hi' is '-hi'
True
2
Hughe

'is' compare l'identité de l'objet alors que == compare les valeurs.

Exemple:

a=[1,2]
b=[1,2]
#a==b returns True
#a is b returns False

p=q=[1,2]
#p==q returns True
#p is q returns True
2
Karthik C

Vous ne pouvez pas surcharger l'opérateur is. Ce que vous voulez surcharger, c'est l'opérateur ==. Cela peut être fait en définissant une méthode __eq__ dans la classe.

1
iform

Vous utilisez la comparaison d'identité. == est probablement ce que vous voulez. L'exception à cette règle est lorsque vous souhaitez vérifier si un élément et un autre sont le même objet EXACT et se trouvent dans la même position de mémoire. Dans vos exemples, les éléments ne sont pas les mêmes, car l'un est d'un type différent (my_string) de l'autre (chaîne). De plus, il n’existe pas de classe générique .__is__ en python (à moins que, bien sûr, vous le mettiez vous-même). Si c'était le cas, comparer des objets avec is ne serait pas fiable pour comparer simplement les emplacements de mémoire.

La première fois que j'ai rencontré le mot clé is, cela m'a aussi perturbé. J'aurais pensé que is et == n'étaient pas différents. Ils ont produit la même sortie de l'interprète sur de nombreux objets. Ce type d’hypothèse est en réalité EXACTEMENT à quoi est ... est destiné. C'est l'équivalent en python "Hey, ne confondez pas ces deux objets. Ils sont différents.", C'est essentiellement ce que [celui qui m'a corrigé] a dit. Formulé très différemment, mais un point == l'autre point.

le pour quelques exemples utiles et un texte pour vous aider avec les différences parfois source de confusion visiter un document de l'hôte mail de python.org écrit par "Danny Yoo"

ou, si cela est hors ligne, utilisez le non listé Pastebin j'ai fait de son corps.

au cas où ils, dans une vingtaine de lunes bleues (les lunes bleues sont un événement réel), sont tous les deux en panne, je citerai les exemples de code

###
>>> my_name = "danny"
>>> your_name = "ian"
>>> my_name == your_name
0                #or False
###

###
>>> my_name[1:3] == your_name[1:3]
1    #or True
###

###
>>> my_name[1:3] is your_name[1:3]
0
###
1
Twisted Code

Les erreurs d'assertion peuvent facilement survenir avec is mot clé lors de la comparaison d'objets. Par exemple, les objets a et b peuvent contenir la même valeur et partager la même adresse mémoire. Par conséquent, faire un 

>>> a == b

va évaluer à 

True

Mais si

>>> a is b

évalue à 

False

vous devriez probablement vérifier 

>>> type(a)

et 

>>> type(b)

Celles-ci pourraient être différentes et une raison d'échec.

0
unixia