Seite 1 von 2

---is---

Verfasst: Samstag 9. Oktober 2010, 00:19
von pythonstarter
Kann mir das jemand erklären?

Code: Alles auswählen

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

Re: ---is---

Verfasst: Samstag 9. Oktober 2010, 00:31
von 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.

Re: ---is---

Verfasst: Samstag 9. Oktober 2010, 06:52
von snafu
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:`).

Re: ---is---

Verfasst: Samstag 9. Oktober 2010, 09:52
von sma
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

Re: ---is---

Verfasst: Samstag 9. Oktober 2010, 09:57
von snafu
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

Re: ---is---

Verfasst: Samstag 9. Oktober 2010, 10:03
von sma
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        

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 11:05
von mutetella
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.

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 11:17
von 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.

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 11:25
von mutetella
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:

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 11:35
von mutetella
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.

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 11:45
von BlackJack
@mutetella: Den letzten Beitrag verstehe ich nicht!?

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 11:57
von DasIch
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?

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 13:07
von 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 ...

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 13:38
von Darii
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.

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 13:58
von snafu
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. :)

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 15:44
von 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.

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 16:22
von mutetella
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...

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 16:44
von DasIch
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

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 16:53
von mutetella
@DasIch: Du hast den Witz schon verstanden, oder? Und falls nicht: Sollte ich dann nicht eher Tabs statt Leerzeichen verwenden?

Re: ---is---

Verfasst: Sonntag 10. Oktober 2010, 16:55
von cofi
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.