2010-05-14 3 views
5

So habe ich eine Motto:Python Verhalten für reichen Vergleich (Oder wenn Dezimal (‚100.0‘) <.01)

import decimal; h = decimal.Decimal('100.0'); (h > .01, h < .01, h.__gt__(.01), h.__lt__(.01)) 

Alles, was es tut, ist ein Dezimal-Objekt macht 100,0 halten, und vergleicht sie zu .01 (der Schwimmer) auf verschiedene Arten.

Mein Ergebnis ist:

>>> import decimal; h = decimal.Decimal('100.0'); (h > .01, h < .01, h.__gt__(.01), h.__lt__(.01)) 
(False, True, NotImplemented, NotImplemented) 

Aus der Dokumentation: „Ein reiches Vergleichsverfahren kann die Singleton zurückkehren NotImplemented, wenn es nicht um den Betrieb für ein gegebenes Paar von Argumenten nicht implementiert“

Also wirklich, es gibt drei Fragen hier.

  1. Wenn eine reiche Vergleichsmethode NotImplemented zurückgibt, was passiert? Warum erhebt es keine Ausnahme?

  2. Wenn es NotImplemented wird, warum gibt es False im ersten Fall und True in der Sekunde zurück? bool (NotImplemented) sollte eine Konstante sein.

  3. Geht es einfach zurück auf id()? Es scheint keine (oder ja, aber nach hinten):

(diese Zeile ignorieren, wird die Formatierung geschraubt und diese fixiert es)

from decimal import Decimal 
h = Decimal('100.0') 
f = .01 
print h < f, id(h) < id(f) 
print h > f, id(h) > id(f) 

Meine Ergebnisse wurden getestet auf:

Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32 
Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32 

Edit: Dokumentation über die Bestellung: http://docs.python.org/library/stdtypes.html#comparisons

Antwort

6

Wenn eine reiche Vergleichsmethode NotImplemented zurückgibt, was passiert? Warum verursacht keine Exception?

es Delegierten das umgekehrten Verfahren (zB __lt__ wenn der Betreiber >) RHS im Vergleich (die float) - die auch in diesem Fall NotImplemented zurück - und schließlich fällt zurück auf Python 2 silly alt Regeln für heterogene Vergleiche.

Wenn es NotImplemented wird, warum es im ersten Fall falsch zurück und Wahre in der zweiten? bool (NotImplemented) sollte eine Konstante sein.

No bool beteiligt - da beide Seiten des Vergleichs NotImplemented zurückkehren (aufgrund einer absichtlichen Design Entscheidung, nicht jede Operation zwischen Dezimalzahlen und Schwimmer unterstützen), die dummen alten Regeln werden als Ausweichlösung verwendet (und in einem recent-genug Version wird die Typen vergleichen, nicht die Instanzen - id hat damit nichts zu tun). In Python 3 würde solch ein nicht unterstützter heterogener Vergleich scheitern und eine klare Ausnahme auslösen, aber in Python 2 kann das aus Gründen der Abwärtskompatibilität nicht passieren - es muss sich so verhalten, wie es sich in Pythons Leben verhalten hat.

Inkompatibilitäten Einführung rückwärts zu beheben, was jetzt Designfehler in Betracht gezogen werden, wie dieser Teil über het Vergleiche, war der Kern Grund zu Python vorstellen 3. Solange Sie Python sind kleben 2 (zB weil sie mehr Erweiterungen von Drittanbietern, etc.), müssen Sie mit diesen Unvollkommenheiten, die nur in Python 3 behoben sind, grinsen und ertragen.

+0

Ah, ich wusste nichts über die Kreuztyp-Sortierung auf dem Typ-Objekt. Danke für deine klare Erklärung. –

+0

Nun, nach viel Handwringen und Bartziehen wurden die Regeln in Python 2.7 ein wenig gelockert: Dezimal- und Float-Instanzen vergleichen sich jetzt sinnvoll miteinander. Das technische Hauptproblem bestand darin, die Regel beizubehalten, dass Zahlen, die mit "Gleich" übereinstimmen, auch gleich "Hash" sein sollten. (Versuchen Sie jedoch nicht, Dezimal - und Bruchinstanzen zu vergleichen!) –

0

Ich habe Python 2.6.4 und Ihr Beispiel funktioniert gut d. h., ich finde

(True, False, NotImplemented, NotImplemented) 

was erwartet wird. Ich weiß nicht, warum Sie unterschiedliche Ergebnisse erhalten.

Über id: id hat nichts mit Vergleichen zu tun, so unter keinen Umständen sollten Sie a und b von id(a) < id(b) vergleichen, die keinen Sinn macht. id ist ein bisschen wie eine Adresse im Speicher, daher macht es keinen Sinn, sie zu vergleichen.

+0

ID() wird als letztes Mittel verwendet, um Objekte zu sortieren, wenn die Objekte keine eigenen Vergleiche definieren. Ich erinnere mich nicht genau, wann es benutzt wird, aber es ist definitiv. Du hast Recht, dass es keinen Sinn ergibt, es sei denn, du versuchst zu garantieren, dass "Objekte konsistent, aber willkürlich geordnet sind (so dass das Sortieren eines heterogenen Arrays ein konsistentes Ergebnis liefert)", was, wie die Dokumente zeigen, Python ist tut. –

+0

es passiert einfach so für Sie: versuchen Sie 999.01 statt 0.1 und Sie sehen genau die gleichen Ergebnisse, zeigen Ihnen ** ** nicht ** "gut" (es ist eine angehaltene Uhr: zweimal am Tag korrigieren ;-). Die _types_ werden am Ende verglichen (und diese Typvergleiche müssen nicht in verschiedenen Python-Installationen funktionieren), nicht die _values_, wie man normalerweise erwarten würde. –

+0

@CB, 'id' wird als letzter Ausweg für _non-ordering_ Vergleiche (Gleichheit und Ungleichheit) und Hashing verwendet, wo es vollkommen Sinn ergibt; Es wird nie für _Ordering-Vergleiche wie '<' verwendet. Stattdessen vergleichen heterogene Bestellvergleiche die _types_ anstelle des Werts. –