it-swarm.com.de

Wie wird das Schlüsselwort 'is' in Python implementiert?

... das is-Schlüsselwort, das für die Gleichheit in Zeichenfolgen verwendet werden kann.

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

Ich habe sowohl __is__() als auch __eq__() ausprobiert, aber sie funktionierten nicht.

>>> 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

Das Testen von Strings mit is funktioniert nur, wenn die Strings intern sind. Wenn Sie nicht wirklich wissen, was Sie tun, und explizit interned die Zeichenfolgen verwenden, sollten Sie niemalsis für Zeichenfolgen verwenden. 

is prüft auf Identität, nicht auf Gleichheit. Das bedeutet, Python vergleicht einfach die Speicheradresse, in der sich ein Objekt befindet. is beantwortet im Wesentlichen die Frage "Habe ich zwei Namen für dasselbe Objekt?" - Überladen würde das keinen Sinn machen.

Zum Beispiel ist ("a" * 100) is ("a" * 100)False. Normalerweise schreibt Python jeden String an einen anderen Speicherort. Interning geschieht meistens bei String-Literalen.

119
Jochen Ritzel

Der Operator is entspricht dem Vergleich von id(x)-Werten. id ist derzeit implementiert, um Zeiger als Vergleich zu verwenden. Sie können also nicht is selbst überladen und AFAIK auch nicht id.

Also kannst du nicht. Unüblich in Python, aber da ist es.

18
Phil H

Das Python-Schlüsselwort is testet die Objektidentität. Sie sollten es NICHT zum Testen der Zeichenfolge auf Gleichheit verwenden. Es scheint häufig zu funktionieren, da Python-Implementierungen, wie die von vielen sehr hochrangigen Sprachen, ein "Interning" von Zeichenfolgen durchführen. Dies bedeutet, dass String-Literale und -Werte intern in einer Hash-Liste gehalten werden und diejenigen, die identisch sind, als Verweise auf dasselbe Objekt gerendert werden. (Dies ist möglich, weil Python-Zeichenfolgen nicht veränderbar sind).

Sie sollten sich jedoch, wie bei allen Implementierungsdetails, nicht darauf verlassen. Wenn Sie die Gleichheit testen möchten, verwenden Sie den Operator ==. Wenn Sie wirklich die Objektidentität testen möchten, verwenden Sie is ---, und ich würde mir schwer tun, einen Fall zu finden, in dem Sie sich um die String-Objektidentität kümmern sollten. Leider kann man nicht damit rechnen, dass zwei Zeichenketten aufgrund der oben genannten Internierung irgendwie "absichtlich" identische Objektreferenzen sind.

14
Jim Dennis

Das Schlüsselwort is vergleicht Objekte (oder vergleicht eher, wenn zwei Referenzen auf dasselbe Objekt verweisen).

Ich denke, warum gibt es keinen Mechanismus, um Ihre eigene Implementierung bereitzustellen.

Es funktioniert manchmal mit Strings, weil Python Strings 'clever' speichert, so dass sie beim Erstellen von zwei identischen Strings in einem Objekt gespeichert werden.

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

Sie können hoffentlich den Vergleich von Referenzdaten in einem einfachen Kopierbeispiel sehen:

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

Wenn Sie keine Angst vor dem Durcheinander mit Bytecode haben, können Sie COMPARE_OP mit dem Argument 8 ("is") abfangen und patchen, um Ihre Hook-Funktion für Objekte zu verwenden, die verglichen werden. Sehen Sie sich die dis-Dokumentation für das Start-In an.

Und vergessen Sie nicht, auch __builtin__.id() abzufangen, wenn jemand id(a) == id(b) anstelle von a is b ausführt.

5
toriningen

es ist nicht möglich, eine Stringvariable mit einem Stringwert und zwei Stringvariablen zu vergleichen, wenn der String mit '-' beginnt. Meine Python-Version ist 2.6.6

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

'is' vergleicht die Objektidentität, während == Werte vergleicht.

Beispiel:

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

Sie können den Operator is nicht überladen. Was Sie überladen möchten, ist der Operator ==. Dies kann durch Definieren einer __eq__-Methode in der Klasse erfolgen.

1
iform

Sie verwenden einen Identitätsvergleich. == ist wahrscheinlich das, was Sie wollen. Die Ausnahme ist, wenn Sie prüfen möchten, ob ein Element und ein anderes das gleiche Objekt sind und sich an derselben Speicherposition befinden. In Ihren Beispielen sind die Elemente nicht identisch, da einer von einem anderen Typ (my_string) als der andere (String) ist. Es gibt auch keine Klasse .__is__ in Python (es sei denn, Sie haben es natürlich selbst dort hingelegt). Wenn dies der Fall wäre, wäre ein Vergleich von Objekten mit is nicht einfach, um die Speicherorte einfach zu vergleichen.

Als ich zum ersten Mal auf das Schlüsselwort is gestoßen bin, hat es mich auch verwirrt. Ich hätte gedacht, dass ist und == sich nicht unterscheiden. Sie erzeugten vom Dolmetscher für viele Objekte die gleiche Ausgabe. Diese Art der Annahme ist eigentlich GENAU, wofür is ... ist. Es ist das Python-Äquivalent "Hey, verwechsle diese beiden Objekte nicht. Sie sind unterschiedlich." Dies ist im Wesentlichen das, was [derjenige, der mich gerade begradigt hat] sagte. Viel anders formuliert, aber ein Punkt == der andere Punkt.

das für einige hilfreiche Beispiele und Text, der bei den manchmal verwirrenden Unterschieden hilft visit ein Dokument von python.orgs Mail-Host von "Danny Yoo"

wenn dies nicht der Fall ist, verwenden Sie den nicht aufgelisteten Pastebin , den ich aus seinem Körper gemacht habe.

falls sie in etwa 20 blauen Monden (blaue Monde sind ein echtes Ereignis) beide heruntergefahren sind, zitiere ich die Codebeispiele

###
>>> 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

Assertion Fehler können beim Vergleichen von Objekten mit dem Schlüsselwort is auftreten. Beispielsweise können Objekte a und b denselben Wert haben und dieselbe Speicheradresse verwenden. Deshalb machen Sie eine 

>>> a == b

wird zu bewerten 

True

Aber falls

>>> a is b

bewertet zu 

False

sie sollten wahrscheinlich nachsehen 

>>> type(a)

und 

>>> type(b)

Diese können unterschiedlich sein und ein Grund zum Scheitern sein.

0
unixia