---is---

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
pythonstarter
User
Beiträge: 53
Registriert: Donnerstag 15. April 2010, 20:34

Kann mir das jemand erklären?

Code: Alles auswählen

>>>2**5 is 2**5
True
>>> 2**10 is 2**10
False
BlackJack

@pythonstarter: Einmal kommt das selbe Objekt als Ergebnis heraus und beim anderen mal sind es zwei unterschiedliche (aber gleiche) Objekte. Warum das so ist braucht Dich nicht zu interessieren. Das Einzige was Du wissen musst, ist das es keine Garantien dafür gibt, dass bei Rechnungen mit Zahlen bei gleichen Werten auch die selben Objekte dahinter stehen. Das gleiche gilt für Zeichenketten.

``is`` testet auf Objektidentität und nicht nur auf Gleichheit. Und bei "immutable" Objekten kann die Python-Implementierung Exemplare cachen und wiederverwenden, weil man den Unterschied nicht bemerkt, denn die Objekte sind ja unveränderbar und verhalten sich gleich wenn sie den gleichen Wert haben.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und um einem möglichen Denkfehler zuvor zu kommen: Während Schlüsselworte wie `or` oder `and` für das entsprechende Symbol/Operator stehen (`||` bzw `&&`), steht `is` nicht für Wertegleichheit (`==`).

`is` setzt man, wie schon gesagt wurde, nur dann ein, wenn man wirklich das selbe Objekt meint, welches an unterschiedliche Namen gebunden sein könnte und wenn man auf `None` testet (`if value is None:`).
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Wer wissen will, bis zu welcher Zahl Python die Zahlenobjekte aufhebt und ab welcher Zahl immer wieder neue Objekte (für die dann der `is`-Vergleich fehlschlägt), kann ja mal folgendes probieren:

Code: Alles auswählen

i = j = 0
while i is j:
    i += 1
    j += 1
print i
Stefan
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Nicht wirklich...

Code: Alles auswählen

>>> i = j = 0
>>> while i is j:
...  i += 1
...  j += 1
... 
>>> print i
257
>>> 257 is 257
True
>>> 258 is 258
True
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Doch. Wenn du zwei Literale vergleichst, funktioniert `is` immer, das sagt nichts aus:

Code: Alles auswählen

>>> 30000 is 30000
True
Wenn du aber eine Operation dabei ausführst, geht's nur bis 256:

Code: Alles auswählen

>>> 256+1 is 256+1
False
Stefan

PS:

Code: Alles auswählen

>>> def a(): return 30000 is 30000
>>> dis.dis(a)
  1           0 LOAD_CONST               1 (30000)
              3 LOAD_CONST               1 (30000)
              6 COMPARE_OP               8 (is)
              9 RETURN_VALUE        
>>> def a(): return 256+1 is 256+1
>>> dis.dis(a)
  1           0 LOAD_CONST               3 (257)
              3 LOAD_CONST               4 (257)
              6 COMPARE_OP               8 (is)
              9 RETURN_VALUE        
>>> def a(): return 257-1 is 257-1
>>> dis.dis(a)
  1           0 LOAD_CONST               3 (256)
              3 LOAD_CONST               4 (256)
              6 COMPARE_OP               8 (is)
              9 RETURN_VALUE        
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Bitte, steinigt mich jetzt nicht... :wink:

Kann man davon ausgehen, dass

Code: Alles auswählen

256 == 256
schneller verarbeitet wird als

Code: Alles auswählen

256 is 256
Demnach Rechenoperationen, die mit Werten und Ergebnissen < 256 schneller sind? Wenn auch nur im mikromikromikro-Bereich.
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Ist das nicht egal? Bei ``==`` kommt hier immer `True` als Ergebnis, bei ``is`` ist das Ergebnis von der Definition der Programmiersprache her undefiniert, die Operation ist also hier nicht wirklich brauchbar.

Allgmein kann man sagen, dass ``is`` im Schnitt schneller ist, weil ``==`` beliebigen Code ausführen kann, je nachdem wie das eben auf den Typen der Objekte definiert ist, während ``is`` immer das gleiche macht und fest in der Sprachimplementierung einmal für alle Objekte definiert ist.

Das sollte aber speziell Leute die gerne optimieren bevor das Programm fertig ist ;-), jetzt nicht dazu verleiten zu schauen wo sie überall ``is`` einsetzen könnten, denn im Zweifelsfall liefert das zwar schneller ein Ergebnis aber ein potentiell *falsches* Ergebnis. Wenn man auf Wertegleichheit testen will, dann ist ``==`` die richtige Wahl. ``is`` ist für einen Vergleich auf Objektidentität, und den braucht man eher selten. Hauptsächlich für den Test auf Singletons wie `None` oder wenn man sich für einen Algorithmus selbst ein eindeutiges "Sentinel"-Objekt erstellt hat.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:Das sollte aber speziell Leute die gerne optimieren bevor das Programm fertig ist ;-), jetzt nicht dazu verleiten zu schauen wo sie überall ``is`` einsetzen könnten, denn im Zweifelsfall liefert das zwar schneller ein Ergebnis aber ein potentiell *falsches* Ergebnis.
Nun ja, mein Gedanke war jetzt schon, darauf zu achten, dass mögliche Ergebnisse 256 nicht überschreiten, damit ich eben den performanteren is-Operator einsetzen kann.
Du wirst sehen, die Geschwindigkeit meines Kalenders wird Dir Wasser in die Augen treiben... :wink:
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Aber jetzt einmal im Ernst:
Mir kam gerade die Frage in den Sinn, ob das Verhalten, das Python hier verwendet, auch in Programmen verwendet wird. Also unendliche Ergebnislisten, für die sich Mechanismen wie beispielsweise ein Generator nicht eignet, zu begrenzen, damit innerhalb einer zuvor festgelegten Wahrscheinlichkeit schnellstmöglich ein ebensolches Ergebnis bereitgestellt werden kann.
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Den letzten Beitrag verstehe ich nicht!?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

mutetella hat geschrieben:Nun ja, mein Gedanke war jetzt schon, darauf zu achten, dass mögliche Ergebnisse 256 nicht überschreiten, damit ich eben den performanteren is-Operator einsetzen kann.
Dir ist klar dass wir hier von Interpreter spezifischem Verhalten reden womit du allerhöchstens kaputten Code produzierst?
lunar

BlackJack hat geschrieben:@mutetella: Den letzten Beitrag verstehe ich nicht!?
Ich glaube, dass er sich fragt, ob die Technik, zwecks Beschleunigung bestimmte Exemplare "kleiner" Objekte vorzuhalten, so wie es bei "int" oder "str" der Fall ist, nur auf den Interpreter beschränkt ist, oder auch generell in Python-Quelltext Anwendung findet.

Falls das tatsächlich die Frage war, so würde ich sie pauschal mit Nein beantworten. Im Allgemeinen ist das Objektmodell von Python ist zu komplex, als dass eine solche Mikrooptimierung nennenswerte Resultate erzielen könnte. Zudem ist es eigentlich die Verantwortung der Laufzeitumgebung, Objektexemplare zu cachen und bei Bedarf wiederzuverwenden, so wie es die JVM meines Wissens tut.

Sowas macht man allenfalls in C oder C++, und da auch nur, wenn wirklich feststeht, dass Objektallokation und Exemplarinitialisierung zu langsam sind.

mutetella, auf die Gefahr hin, mich zu wiederholen, sage ich Dir, dass es nichts wird mit Dir und Deinen Programmen, wenn Du Dich weiterhin so zwanghaft um solche Kleinigkeiten sorgst. Nichts für ungut ...
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mutetella hat geschrieben:Bitte, steinigt mich jetzt nicht... :wink:

Kann man davon ausgehen, dass

Code: Alles auswählen

256 == 256
schneller verarbeitet wird als

Code: Alles auswählen

256 is 256
Ahh… bloß nicht. Das ist ein Implementierungsdetail, auf das man sich auf keinen Fall verlassen sollte. Verwende `is` nur, wenn du wirklich auf die Identität testen will, sonst nicht.

`is` ist übrigens nur bei CPython schneller, bei Pypy ist es sogar langsamer, da die Objektidentität dort nicht einfach aus dem Zeiger auf das Objekt abgeleitet werden kann.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich würde ja empfehlen, alle Namen in C64-Manier abzukürzen. Ich bin mir sicher, dass man damit auch nochmal das letzte bißchen aus dem Kalendarprogramm herauskitzeln kann, weil kürzere Namen ja weniger Bytes belegen. Falls du Generatoren benutzt (machst du bestimmt), dann arbeite bitte mit mindestens vierfacher Verschachtelungstiefe. Nur so kann dein Programm wirklich gut und erfolgreich werden. :)
BlackJack

@snafu: Das wäre eher `CBM BASIC`-Manier als `C64-Manier`. Es gibt auf dem und für den C64 durchaus Programmiersprachen und Compiler, die mehr als zwei signifikante Zeichen (+ Typ-Sigil) für Bezeichner berücksichtigen. :-)

Bei den meisten Implementierungen auf dem Originalgerät gibt es zwar auch eine harte Obergrenze, die ist mit in der Regel 16 oder 32 Zeichen deutlich programmier- bzw. lesefreundlicher angelegt.

Was die Bezeichner angeht, kann man auf dem C64 mit so ziemlich jedem Makro-Assembler lesbarere Programme schreiben als mit dem eingebauten BASIC.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

lunar hat geschrieben:
BlackJack hat geschrieben:@mutetella: Den letzten Beitrag verstehe ich nicht!?
Ich glaube, dass er sich fragt, ob die Technik, zwecks Beschleunigung bestimmte Exemplare "kleiner" Objekte vorzuhalten, so wie es bei "int" oder "str" der Fall ist, nur auf den Interpreter beschränkt ist, oder auch generell in Python-Quelltext Anwendung findet.
Genau, das meinte ich. Allerdings nicht "zwecks Beschleunigung", sondern weil es keine andere/bessere Möglichkeit gibt.
lunar hat geschrieben:mutetella, auf die Gefahr hin, mich zu wiederholen, sage ich Dir, dass es nichts wird mit Dir und Deinen Programmen, wenn Du Dich weiterhin so zwanghaft um solche Kleinigkeiten sorgst. Nichts für ungut ...
Schon klar, das ist bei mir angekommen und ich versuch' auch, rechtzeitig die Kurve zu bekommen... :) Aus Gründen der Performance den is-Operator einem == vorzuziehen war jetzt auch eher ein doofer Witz von mir.
Allerdings muss es ja einen Grund geben, weshalb Python Zahlen bis 256 bereits als Objekte vorbereitet und weitere Zahlen erst bei Bedarf erzeugt. Und ich dachte mir, dass ein Grund vielleicht auch der ist, dass Zahlen eben unendlich vorhanden sind und von daher gar nicht alle als Objekte zur Verfügung stehen können. Das nur mal als Ausgangspunkt meiner Überlegung. Performance steht dabei für mich gar nicht im Vordergrund, ehrlich!
Nachdem ich in meinem Kalenderprogramm natürlich auch mit unendlichen Ergebnissen zu tun habe, kam ich dann eben auf den Gedanken, ob das Bereitstellen einer bestimmten Anzahl von Objekten aus einer Liste unendlicher dieser Objekte eine Möglichkeit wäre, "Unendlichkeit" in den Griff zu bekommen. Neben Generatoren oder dem Prüfen bestimmter Kriterien eines Objekts.
DasIch hat geschrieben:Dir ist klar dass wir hier von Interpreter spezifischem Verhalten reden womit du allerhöchstens kaputten Code produzierst?
Wie gesagt, das war jetzt eher ein nicht ernst gemeinter Hinweis auf tief verwurzelte Performance-Phopie, die auf Zeiten zurückzuführen ist, in denen ich Stunden und Tage damit verbracht hatte, verschiedenste Kombinationen von LoadHigh (LH) Anweisungen in meiner autoexec.bat zu testen.

@snafu: Vierfache Verschachtelungstiefe ist ein toller Tipp, danke! Allerdings macht mir dieses ständige 16xLeertaste-gehacke echt Schwierigkeiten! Aber da gibt's bestimmt ein VIM-Script für. Ich google das mal...
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

mutetella hat geschrieben:@snafu: Vierfache Verschachtelungstiefe ist ein toller Tipp, danke! Allerdings macht mir dieses ständige 16xLeertaste-gehacke echt Schwierigkeiten! Aber da gibt's bestimmt ein VIM-Script für. Ich google das mal...
Du kannst vim wie jeden anderen (brauchbaren) Editor dazu einstellen Leerzeichen statt Tabs zu verwenden. Meine Python spezifischen Einstellungen findest du z.B. hier
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@DasIch: Du hast den Witz schon verstanden, oder? Und falls nicht: Sollte ich dann nicht eher Tabs statt Leerzeichen verwenden?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

mutetella hat geschrieben:@snafu: Vierfache Verschachtelungstiefe ist ein toller Tipp, danke! Allerdings macht mir dieses ständige 16xLeertaste-gehacke echt Schwierigkeiten! Aber da gibt's bestimmt ein VIM-Script für. Ich google das mal...
Fuer den Fall, dass das ernst gemeint war:

Code: Alles auswählen

set tabstop=4, expandtab
Edit: Nein, wehe du nutzt Tabs!

Zu deiner Unendlichkeitsueberlegung: Warum soll dir das Vorhalten einer _endlichen_ Menge moeglicher Objekte bei der Handhabung einer _unendlichen_ Menge helfen?
Generatoren oder generell das Erzeugen von Objekten wenn sie denn ueberhaupt gebraucht werden, ist die einzige Moeglichkeit damit umzugehen.

Wenn du dir aufgrund deines Kaffeesatzes 10 beliebige Daten von heute bis zum Erscheinen von Duke Nukem Forever rauspickst, ist das keine Hilfe. Sind es die naechsten 10, dann ist das eine "Optimierung" mit der Annahme, dass die haeufig gebraucht werden.
Antworten