Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 238 – Änderung des Divisionsoperators

Autor:
Moshe Zadka <moshez at zadka.site.co.il>, Guido van Rossum <guido at python.org>
Status:
Final
Typ:
Standards Track
Erstellt:
11. März 2001
Python-Version:
2.2
Post-History:
16. März 2001, 26. Juli 2001, 27. Juli 2001

Inhaltsverzeichnis

Zusammenfassung

Der aktuelle Divisionsoperator (/) hat bei numerischen Argumenten eine mehrdeutige Bedeutung: Er gibt den ganzzahligen Teil des mathematischen Divisionsergebnisses zurück, wenn die Argumente ganze Zahlen (ints oder longs) sind, aber er gibt eine vernünftige Annäherung des Divisionsergebnisses zurück, wenn die Argumente Gleitkommazahlen (floats) oder komplexe Zahlen sind. Dies macht Ausdrücke, die Gleitkomma- oder komplexe Ergebnisse erwarten, fehleranfällig, wenn ganze Zahlen nicht erwartet werden, aber als Eingabe möglich sind.

Wir schlagen vor, dies zu beheben, indem wir unterschiedliche Operatoren für unterschiedliche Operationen einführen: x/y, um eine vernünftige Annäherung des mathematischen Divisionsergebnisses zu erhalten ("wahre Division"), und x//y, um den ganzzahligen Teil zu erhalten ("Ganzzahldivision"). Die aktuelle, gemischte Bedeutung von x/y bezeichnen wir als "klassische Division".

Aufgrund schwerwiegender Probleme mit der Abwärtskompatibilität und nicht zuletzt eines großen Streits in c.l.py schlagen wir die folgenden Übergangsmaßnahmen vor (beginnend mit Python 2.2)

  • Die klassische Division bleibt der Standard in der Python 2.x-Serie; die wahre Division wird in Python 3.0 zum Standard.
  • Der Operator // wird verfügbar sein, um die Ganzzahldivision eindeutig anzufordern.
  • Die zukünftige Anweisung für die Division, from __future__ import division, ändert den Operator / so, dass er im gesamten Modul die wahre Division bedeutet.
  • Eine Kommandozeilenoption wird Laufzeitwarnungen für die klassische Division aktivieren, wenn sie auf ganze Zahlen (int oder long) angewendet wird; eine weitere Kommandozeilenoption wird die wahre Division zum Standard machen.
  • Die Standardbibliothek wird die zukünftige Anweisung für die Division und den Operator // verwenden, wo dies angebracht ist, um die klassische Division vollständig zu vermeiden.

Motivation

Der klassische Divisionsoperator erschwert das Schreiben von numerischen Ausdrücken, die korrekte Ergebnisse für beliebige numerische Eingaben liefern sollen. Für alle anderen Operatoren kann man eine Formel wie x*y**2 + z aufschreiben, und das berechnete Ergebnis wird (innerhalb der Grenzen der numerischen Genauigkeit, versteht sich) für jeden numerischen Eingabetyp (int, long, float oder complex) nahe am mathematischen Ergebnis liegen. Die Division stellt jedoch ein Problem dar: Wenn die Ausdrücke für beide Argumente zufällig einen ganzzahligen Typ haben, wird stattdessen die Ganzzahldivision implementiert, nicht die wahre Division.

Das Problem ist einzigartig für dynamisch typisierte Sprachen: In einer statisch typisierten Sprache wie C werden die Eingaben, typischerweise Funktionsargumente, als double oder float deklariert, und wenn ein ganzzahliger Argument übergeben wird, wird er zum Zeitpunkt des Aufrufs in double oder float konvertiert. Python hat keine Argumenttypdeklarationen, so dass ganzzahlige Argumente leicht in einen Ausdruck gelangen können.

Das Problem ist besonders heimtückisch, da Ganzzahlen in allen anderen Umständen perfekte Ersatz für Gleitkommazahlen sind: math.sqrt(2) gibt denselben Wert zurück wie math.sqrt(2.0), 3.14*100 und 3.14*100.0 ergeben denselben Wert und so weiter. Daher kann der Autor einer numerischen Routine nur Gleitkommazahlen zum Testen seines Codes verwenden und glauben, dass er korrekt funktioniert, und ein Benutzer kann versehentlich einen ganzzahligen Eingabewert übergeben und falsche Ergebnisse erhalten.

Eine andere Sichtweise ist, dass die klassische Division das Schreiben von polymorphen Funktionen erschwert, die sowohl mit Gleitkomma- als auch mit Ganzzahlargumenten gut funktionieren; alle anderen Operatoren machen bereits das Richtige. Kein Algorithmus, der sowohl für Ganzzahlen als auch für Gleitkommazahlen funktioniert, benötigt in einem Fall eine küzende Division und im anderen eine wahre Division.

Die korrekte Umgehung ist subtil: Das Umwandeln eines Arguments in float() ist falsch, wenn es sich um eine komplexe Zahl handeln könnte; das Hinzufügen von 0.0 zu einem Argument bewahrt das Vorzeichen des Arguments nicht, wenn es sich um Minus Null handelte. Die einzige Lösung ohne einen der beiden Nachteile ist die Multiplikation eines Arguments (typischerweise des ersten) mit 1.0. Dies lässt den Wert und das Vorzeichen für float und complex unverändert und wandelt int und long in ein float mit dem entsprechenden Wert um.

Es ist die Meinung der Autoren, dass dies ein echtes Designproblem in Python ist und dass es früher oder später behoben werden sollte. Angesichts des fortlaufenden Wachstums der Python-Nutzung werden die Kosten für die Beibehaltung dieses Fehlers in der Sprache irgendwann die Kosten für die Korrektur alter Codes überwiegen – es gibt eine Obergrenze für die zu korrigierende Code-Menge, aber die Menge des Codes, der möglicherweise zukünftig von dem Fehler betroffen ist, ist unbegrenzt.

Ein weiterer Grund für diese Änderung ist der Wunsch, Pythons numerisches Modell letztendlich zu vereinheitlichen. Dies ist das Thema von PEP 228 (das derzeit unvollständig ist). Ein vereinheitlichtes numerisches Modell beseitigt den meisten Bedarf des Benutzers, sich unterschiedlicher numerischer Typen bewusst zu sein. Dies ist gut für Anfänger, nimmt aber auch fortgeschrittenen Programmierern Bedenken hinsichtlich unterschiedlichen numerischen Verhaltens. (Natürlich werden Bedenken hinsichtlich numerischer Stabilität und Genauigkeit nicht beseitigt.)

In einem vereinheitlichten numerischen Modell dienen die verschiedenen Typen (int, long, float, complex und möglicherweise andere, wie ein neuer rationaler Typ) hauptsächlich zur Speicheroptimierung und bis zu einem gewissen Grad zur Anzeige orthogonaler Eigenschaften wie Ungenauigkeit oder Komplexität. In einem vereinheitlichten Modell sollte die Ganzzahl 1 von der Gleitkommazahl 1.0 (abgesehen von ihrer Ungenauigkeit) nicht zu unterscheiden sein, und beide sollten sich in allen numerischen Kontexten gleich verhalten. Klar, in einem vereinheitlichten numerischen Modell sollte, wenn a==b und c==d, a/c gleich b/d sein (unter Berücksichtigung einiger Freiheiten aufgrund von Rundung bei ungenauen Zahlen), und da sich alle einig sind, dass 1.0/2.0 gleich 0.5 ist, sollte auch 1/2 gleich 0.5 sein. Ebenso sollte, da 1//2 gleich Null ist, auch 1.0//2.0 gleich Null sein.

Variationen

Ästhetisch gefällt x//y nicht jedem, und daher wurden mehrere Variationen vorgeschlagen. Diese werden hier behandelt

  • x div y. Dies würde ein neues Schlüsselwort einführen. Da div ein beliebter Bezeichner ist, würde dies eine beträchtliche Menge vorhandenen Codes brechen, es sei denn, das neue Schlüsselwort würde nur unter einer zukünftigen Anweisung für die Division erkannt. Da erwartet wird, dass der Großteil des Codes, der konvertiert werden muss, ganze Zahlen teilt, würde dies die Notwendigkeit der zukünftigen Anweisung für die Division erheblich erhöhen. Selbst mit einer zukünftigen Anweisung spricht die allgemeine Stimmung gegen die Hinzufügung neuer Schlüsselwörter, es sei denn, dies ist absolut notwendig, dagegen.
  • div(x, y). Dies macht die Konvertierung von altem Code wesentlich schwieriger. Das Ersetzen von x/y durch x//y oder x div y kann mit einer einfachen Suchen-und-Ersetzen-Funktion erfolgen; in den meisten Fällen kann der Programmierer leicht überprüfen, dass ein bestimmtes Modul nur mit ganzen Zahlen funktioniert, sodass alle Vorkommen von x/y ersetzt werden können. (Die Suchen-und-Ersetzen-Funktion ist immer noch erforderlich, um Schrägstriche zu entfernen, die in Kommentaren oder Zeichenkettenliteralen vorkommen.) Das Ersetzen von x/y durch div(x, y) würde ein wesentlich intelligenteres Werkzeug erfordern, da die Ausdehnung der Ausdrücke links und rechts von / analysiert werden muss, bevor die Platzierung des div( und ) bestimmt werden kann.
  • x \ y. Der Backslash ist bereits ein Token und bedeutet Zeilenfortsetzung, und im Allgemeinen suggeriert er für Unix-Benutzer ein *Escape*. Zusätzlich (dies von Terry Reedy) würde dies das korrekte Verarbeiten von eval("x\y") erschweren.

Alternativen

Um die Menge des alten Codes, der konvertiert werden muss, zu reduzieren, wurden mehrere alternative Vorschläge unterbreitet. Hier ist eine kurze Diskussion jedes Vorschlags (oder jeder Kategorie von Vorschlägen). Wenn Sie eine Alternative kennen, die auf c.l.py diskutiert wurde und hier nicht erwähnt wird, senden Sie bitte eine E-Mail an den zweiten Autor.

  • Der Operator / behält seine klassische Semantik; // wird für die wahre Division eingeführt. Dies hinterlässt immer noch einen fehlerhaften Operator in der Sprache und lädt dazu ein, das fehlerhafte Verhalten zu nutzen. Es versperrt auch den Weg zu einem vereinheitlichten numerischen Modell im Stil von PEP 228.
  • Ganzzahldivision gibt einen speziellen "Portmanteau"-Typ zurück, der sich im ganzzahligen Kontext wie eine Ganzzahl verhält, aber im Gleitkommakontext wie eine Gleitkommazahl. Das Problem dabei ist, dass nach einigen Operationen der Ganzzahl- und der Gleitkommawert meilenweit auseinanderliegen könnten, unklar ist, welcher Wert in Vergleichen verwendet werden soll, und viele Kontexte (wie die Konvertierung in eine Zeichenkette) keine klare Präferenz für Ganzzahlen oder Gleitkommazahlen haben.
  • Verwenden Sie eine Direktive, um eine spezifische Divisionssemantik in einem Modul zu verwenden, anstatt einer zukünftigen Anweisung. Dies behält die klassische Division als permanente Narbe in der Sprache bei und erfordert, dass zukünftige Generationen von Python-Programmierern sich des Problems und der Abhilfemaßnahmen bewusst sind.
  • Verwenden Sie from __past__ import division, um die klassische Divisionssemantik in einem Modul zu verwenden. Dies behält auch die klassische Division als permanente Narbe bei, oder zumindest für lange Zeit (letztendlich könnte die Anweisung für die vergangene Division einen ImportError auslösen).
  • Verwenden Sie eine Direktive (oder eine andere Methode), um die Python-Version anzugeben, für die ein bestimmter Codeabschnitt entwickelt wurde. Dies erfordert, dass zukünftige Python-Interpreter *genau* mehrere frühere Python-Versionen emulieren können, und darüber hinaus dies für mehrere Versionen innerhalb desselben Interpreters tun. Dies ist viel zu viel Arbeit. Eine wesentlich einfachere Lösung ist die Installation mehrerer Interpreter. Ein weiteres Argument dagegen ist, dass die Versionsdirektive fast immer übermäßig spezifiziert ist: Die meisten für Python X.Y geschriebenen Codes funktionieren auch für Python X.(Y-1) und X.(Y+1), sodass die Angabe von X.Y als Version einschränkender ist als nötig. Gleichzeitig gibt es keine Möglichkeit zu wissen, bei welcher zukünftigen oder vergangenen Version der Code fehlschlägt.

API-Änderungen

Während der Übergangsphase müssen wir *drei* Divisionsoperatoren im selben Programm unterstützen: klassische Division (für / in Modulen ohne zukünftige Anweisung für die Division), wahre Division (für / in Modulen mit zukünftiger Anweisung für die Division) und Ganzzahldivision (für //). Jeder Operator kommt in zwei Varianten: regulär und als erweiterter Zuweisungsoperator (/= oder //=).

Die Namen, die mit diesen Variationen verbunden sind, sind

  • Überladene Operator-Methoden
    __div__(), __floordiv__(), __truediv__();
    __idiv__(), __ifloordiv__(), __itruediv__().
    
  • Abstrakte C-API-Funktionen
    PyNumber_Divide(), PyNumber_FloorDivide(),
    PyNumber_TrueDivide();
    
    PyNumber_InPlaceDivide(), PyNumber_InPlaceFloorDivide(),
    PyNumber_InPlaceTrueDivide().
    
  • Bytecode-Opcodes
    BINARY_DIVIDE, BINARY_FLOOR_DIVIDE, BINARY_TRUE_DIVIDE;
    INPLACE_DIVIDE, INPLACE_FLOOR_DIVIDE, INPLACE_TRUE_DIVIDE.
    
  • PyNumberMethod-Slots
    nb_divide, nb_floor_divide, nb_true_divide,
    nb_inplace_divide, nb_inplace_floor_divide,
    nb_inplace_true_divide.
    

Die hinzugefügten PyNumberMethod-Slots erfordern ein zusätzliches Flag in tp_flags; dieses Flag wird Py_TPFLAGS_HAVE_NEWDIVIDE heißen und wird in Py_TPFLAGS_DEFAULT enthalten sein.

Die APIs für wahre Division und Ganzzahldivision suchen nach den entsprechenden Slots und rufen diese auf; wenn der Slot NULL ist, lösen sie eine Ausnahme aus. Es gibt keinen Fallback auf den klassischen Divisionsslot.

In Python 3.0 wird die klassische Divisionssemantik entfernt; die klassischen Divisions-APIs werden synonym mit der wahren Division.

Kommandozeilenoption

Die Kommandozeilenoption -Q nimmt ein String-Argument entgegen, das vier Werte annehmen kann: old, warn, warnall oder new. Der Standard ist old in Python 2.2, wird aber in späteren 2.x-Versionen zu warn geändert. Der Wert old bedeutet, dass der klassische Divisionsoperator wie beschrieben funktioniert. Der Wert warn bedeutet, dass der klassische Divisionsoperator eine Warnung ausgibt (eine DeprecationWarning über das Standard-Warnsystem), wenn er auf ganze Zahlen oder longs angewendet wird. Der Wert warnall gibt ebenfalls Warnungen für klassische Divisionen aus, wenn sie auf floats oder complex angewendet werden; dies ist für die Verwendung durch das unten erwähnte Konvertierungsskript fixdiv.py gedacht. Der Wert new ändert den Standard global, sodass der Operator / immer als wahre Division interpretiert wird. Die Option new ist nur für bestimmte Bildungsumgebungen gedacht, in denen die wahre Division erforderlich ist, aber die Studenten aufzufordern, die zukünftige Anweisung für die Division in allen ihren Codes einzufügen, wäre ein Problem.

Diese Option wird in Python 3.0 nicht unterstützt; Python 3.0 wird / immer als wahre Division interpretieren.

(Diese Option wurde ursprünglich als -D vorgeschlagen, aber das stellte sich als bereits existierende Option für Jython heraus, daher das Q – Mnemonic für Quotient. Andere Namen wurden vorgeschlagen, wie -Qclassic, -Qclassic-warn, -Qtrue oder -Qold_division usw.; diese scheinen mir wortreicher, ohne viel Vorteil. Schließlich wird der Begriff "klassische Division" in der Sprache überhaupt nicht verwendet (nur im PEP), und der Begriff "wahre Division" wird selten in der Sprache verwendet – nur in __truediv__.)

Semantik der Ganzzahldivision

Die Ganzzahldivision wird in allen Python-numerischen Typen implementiert und hat die Semantik von

a // b == floor(a/b)

mit der Ausnahme, dass der Ergebnistyp der gemeinsame Typ ist, in den *a* und *b* vor der Operation koerziert werden.

Insbesondere, wenn *a* und *b* vom selben Typ sind, ist a//b auch von diesem Typ. Wenn die Eingaben unterschiedliche Typen haben, werden sie zuerst unter Verwendung derselben Regeln wie für alle anderen arithmetischen Operatoren zu einem gemeinsamen Typ koerziert.

Insbesondere, wenn *a* und *b* beide ganze Zahlen (int oder long) sind, hat das Ergebnis denselben Typ und Wert wie bei der klassischen Division für diese Typen (einschließlich des Falls von gemischten Eingabetypen; int//long und long//int geben beide einen long zurück).

Für Gleitkommaeingaben ist das Ergebnis ein float. Zum Beispiel

3.5//2.0 == 1.0

Für komplexe Zahlen löst // eine Ausnahme aus, da floor() einer komplexen Zahl nicht erlaubt ist.

Für benutzerdefinierte Klassen und Erweiterungstypen liegt die gesamte Semantik bei der Implementierung der Klasse oder des Typs.

Semantik der wahren Division

Die wahre Division für ganze Zahlen (int und long) konvertiert die Argumente in float und wendet dann eine Float-Division an. Das bedeutet, selbst 2/1 gibt einen float (2.0) zurück, keine int. Für floats und complex wird sie dieselbe sein wie die klassische Division.

Die 2.2-Implementierung der wahren Division verhält sich so, als ob der Float-Typ einen unbegrenzten Bereich hätte, sodass kein Überlauf auftritt, es sei denn, die Größenordnung des mathematischen *Ergebnisses* ist zu groß, um als Float dargestellt zu werden. Zum Beispiel löst nach x = 1L << 40000, float(x) einen OverflowError aus (beachten Sie, dass dies ebenfalls neu in 2.2 ist: zuvor war das Ergebnis plattformabhängig, meistens eine Float-Unendlichkeit). Aber x/x gibt 1.0 ohne Ausnahme zurück, während x/1 einen OverflowError auslöst.

Beachten Sie, dass für int- und long-Argumente die wahre Division Informationen verlieren kann; dies liegt in der Natur der wahren Division (solange keine rationalen Zahlen in der Sprache vorhanden sind). Algorithmen, die bewusst longs verwenden, sollten die Verwendung von // in Betracht ziehen, da die wahre Division von longs nicht mehr als 53 Bits Präzision beibehält (auf den meisten Plattformen).

Wenn und wann ein rationaler Typ zu Python hinzugefügt wird (siehe PEP 239), sollte die wahre Division für int und long wahrscheinlich eine rationale Zahl zurückgeben. Dies vermeidet das Problem des Informationsverlusts bei der wahren Division von int und long. Aber bis dahin ist aus Konsistenzgründen float die einzige Wahl für die wahre Division.

Die zukünftige Anweisung für die Division

Wenn from __future__ import division in einem Modul vorhanden ist oder wenn -Qnew verwendet wird, werden die Operatoren / und /= in Opcodes für die wahre Division übersetzt; andernfalls werden sie in die klassische Division übersetzt (bis Python 3.0 erscheint, wo sie immer in die wahre Division übersetzt werden).

Die zukünftige Anweisung für die Division hat keinen Einfluss auf die Erkennung oder Übersetzung von // und //=.

Siehe PEP 236 für die allgemeinen Regeln für zukünftige Anweisungen.

(Es wurde vorgeschlagen, eine längere Formulierung wie *true_division* oder *modern_division* zu verwenden. Diese scheinen nicht viel Information hinzuzufügen.)

Offene Fragen

Wir erwarten, dass diese Probleme im Laufe der Zeit gelöst werden, wenn mehr Feedback eingeht oder wir mehr Erfahrung mit der anfänglichen Implementierung sammeln.

  • Es wurde vorgeschlagen, // den Quotientenoperator und den Operator / den Verhältnisoperator zu nennen. Ich bin mir da nicht sicher – für manche Leute ist Quotient nur ein Synonym für Division, und Verhältnis deutet auf rationale Zahlen hin, was falsch ist. Ich bevorzuge es, wenn die Terminologie leicht unbeholfen ist, wenn das Unambigue vermeidet wird. Außerdem deutet *Quotient* für manche Leute auf eine Kürzung in Richtung Null hin, nicht in Richtung Unendlich, wie es *Ganzzahldivision* explizit besagt.
  • Es wurde argumentiert, dass eine Kommandozeilenoption zur Änderung des Standards böse ist. Sie kann in den falschen Händen sicherlich gefährlich sein: Zum Beispiel wäre es unmöglich, ein Drittanbieter-Bibliothekspaket, das -Qnew benötigt, mit einem anderen zu kombinieren, das -Qold benötigt. Aber ich glaube, dass die VPython-Leute eine Möglichkeit brauchen, die wahre Division standardmäßig zu aktivieren, und andere Pädagogen vielleicht dasselbe brauchen. Diese haben normalerweise genug Kontrolle über die verfügbaren Bibliotheken in ihrer Umgebung.
  • Dass Klassen alle drei von __div__(), __floordiv__() und __truediv__() unterstützen müssen, scheint mühsam; und was tun wir in 3.0? Vielleicht brauchen wir nur __div__() und __floordiv__(), oder vielleicht sollte zumindest die wahre Division zuerst __truediv__() und dann __div__() versuchen.

Gelöste Probleme

  • Problem: Bei sehr großen langen Ganzzahlen verursacht die Definition der wahren Division als Rückgabe eines Floats Probleme, da der Bereich von Python-Longs viel größer ist als der von Python-Floats. Dieses Problem wird verschwinden, wenn und sobald rationale Zahlen unterstützt werden.

    Lösung: Bei der langen wahren Division verwendet Python einen internen Float-Typ mit nativer Doppelpräzision, aber unbegrenztem Bereich, sodass kein OverflowError auftritt, es sei denn, der Quotient ist zu groß, um als natives Double dargestellt zu werden.

  • Problem: In der Zwischenzeit könnte die Long-zu-Float-Konvertierung einen OverflowError auslösen, wenn die Long-Zahl außerhalb des Bereichs liegt.

    Lösung: Dies wurde implementiert, aber wie oben erwähnt, spielt die Größenordnung der Argumente für die lange wahre Division keine Rolle; nur die Größenordnung des Quotienten ist relevant.

  • Problem: Tim Peters wird sicherstellen, dass immer dann, wenn ein Float innerhalb des Bereichs zurückgegeben wird, eine angemessene Präzision gewährleistet ist.

    Lösung: Solange der Quotient der langen wahren Division als Float dargestellt werden kann, treten nicht mehr als 3 Rundungsfehler auf: jeweils einer für die Konvertierung der Argumente in einen internen Float-Typ mit nativer Doppelpräzision, aber unbegrenztem Bereich, und ein weiterer für die Division. Beachten Sie jedoch, dass, wenn die Größenordnung des Quotienten zu *klein* ist, um als natives Double dargestellt zu werden, 0.0 ohne Ausnahme zurückgegeben wird ("stille Unterlauf").

FAQ

Wann wird Python 3.0 veröffentlicht?

Wir planen nicht so weit im Voraus, daher können wir nicht mit Sicherheit sagen. Wir wollen mindestens zwei Jahre für den Übergang einplanen. Wenn Python 3.0 früher erscheint, werden wir die 2.x-Linie bis mindestens zwei Jahre nach der Veröffentlichung von Python 2.2 für Abwärtskompatibilität am Leben erhalten. Tatsächlich können Sie die Python 2.x-Linie noch mehrere Jahre nach der Veröffentlichung von Python 3.0 weiter verwenden, sodass Sie sich mit der Umstellung Zeit lassen können. Es wird erwartet, dass Websites sowohl Python 2.x als auch Python 3.x gleichzeitig installiert haben.

Warum heißt die wahre Division nicht Float-Division?

Da ich die Tür offen halten möchte, um *möglicherweise* rationale Zahlen einzuführen und 1/2 eine rationale Zahl statt eines Floats zurückgeben zu lassen. Siehe PEP 239.

Warum werden __truediv__ und __itruediv__ benötigt?

Wir wollen benutzerdefinierte Klassen nicht zu Bürgern zweiter Klasse machen. Sicherlich nicht mit der laufenden Typ-/Klassenvereinheitlichung.

Wie schreibe ich Code, der sowohl unter den klassischen als auch unter den neuen Regeln funktioniert, ohne // oder eine zukünftige Anweisung für die Division zu verwenden?

Verwenden Sie x*1.0/y für die wahre Division, divmod(x, y) (PEP 228) für die Ganzzahldivision. Insbesondere letzteres ist am besten in einer Funktion versteckt. Sie können auch float(x)/y für die wahre Division schreiben, wenn Sie sicher sind, dass Sie keine komplexen Zahlen erwarten. Wenn Sie wissen, dass Ihre ganzen Zahlen niemals negativ sind, können Sie int(x/y) verwenden – während die Dokumentation von int() besagt, dass int() je nach C-Implementierung runden oder kürzen kann, kennen wir keine C-Implementierung, die nicht kürzt, und wir werden die Spezifikation für int() ändern, um das Kürzen zu versprechen. Beachten Sie, dass die klassische Division (und die Ganzzahldivision) in Richtung negativer Unendlichkeit runden, während int() in Richtung Null rundet, was bei negativen Zahlen zu unterschiedlichen Antworten führt.

Wie lege ich die Divisionssemantik für input(), compile(), execfile(), eval() und exec fest?

Sie erben die Wahl vom aufrufenden Modul. PEP 236 listet dies nun als gelöstes Problem auf und verweist auf PEP 264.

Was ist mit Code, der vom codeop-Modul kompiliert wird?

Dies wird ordnungsgemäß behandelt; siehe PEP 264.

Wird es Konvertierungswerkzeuge oder Hilfsmittel geben?

Sicherlich. Obwohl diese außerhalb des Rahmens des PEP liegen, sollte ich auf zwei einfache Werkzeuge hinweisen, die mit Python 2.2a3 veröffentlicht werden: Tools/scripts/finddiv.py findet Divisionsoperatoren (etwas intelligenter als grep /) und Tools/scripts/fixdiv.py kann Patches basierend auf Laufzeitanalysen erstellen.

Warum wird meine Frage hier nicht beantwortet?

Weil wir es nicht bemerkt haben. Wenn es auf c.l.py diskutiert wurde und Sie glauben, dass die Antwort von allgemeinem Interesse ist, benachrichtigen Sie bitte den zweiten Autor. (Wir haben nicht die Zeit oder Neigung, jede privat gesendete E-Mail zu beantworten, daher die Anforderung, dass es zuerst auf c.l.py diskutiert wird.)

Implementierung

Im Wesentlichen ist alles hier Erwähnte in CVS implementiert und wird mit Python 2.2a3 veröffentlicht; die meisten davon wurden bereits mit Python 2.2a2 veröffentlicht.


Quelle: https://github.com/python/peps/blob/main/peps/pep-0238.rst

Zuletzt geändert: 2025-02-01 08:55:40 GMT