Neues in Python 2.1¶
- Autor:
A.M. Kuchling
Einleitung¶
Dieser Artikel erklärt die neuen Funktionen in Python 2.1. Obwohl es in 2.1 nicht so viele Änderungen wie in Python 2.0 gab, gibt es dennoch einige angenehme Überraschungen. 2.1 ist die erste Veröffentlichung, die mithilfe von Python Enhancement Proposals (PEPs) gesteuert wurde. Daher haben die meisten größeren Änderungen begleitende PEPs, die eine vollständigere Dokumentation und eine Begründung für die Änderung liefern. Dieser Artikel versucht nicht, die neuen Funktionen vollständig zu dokumentieren, sondern bietet lediglich einen Überblick über die neuen Funktionen für Python-Programmierer. Verweisen Sie für weitere Details zu jeder neuen Funktion, die Sie besonders interessiert, auf die Python 2.1-Dokumentation oder die spezifische PEP.
Ein aktuelles Ziel des Python-Entwicklungsteams ist die Beschleunigung des Veröffentlichungszyklus neuer Versionen, mit einer neuen Version alle 6 bis 9 Monate. 2.1 ist die erste Version, die mit dieser schnelleren Frequenz veröffentlicht wird, wobei die erste Alpha-Version im Januar, 3 Monate nach der endgültigen Veröffentlichung von 2.0, erschien.
Die endgültige Veröffentlichung von Python 2.1 erfolgte am 17. April 2001.
PEP 227: Verschachtelte Scopes¶
Die größte Änderung in Python 2.1 betrifft die Scoping-Regeln von Python. In Python 2.0 gibt es zu jedem Zeitpunkt höchstens drei Namensräume, die zum Nachschlagen von Variablennamen verwendet werden: lokal, Modulebene und der eingebaute Namensraum. Dies überraschte viele Leute, da es nicht ihren intuitiven Erwartungen entsprach. Zum Beispiel funktioniert eine verschachtelte rekursive Funktionsdefinition nicht
def f():
...
def g(value):
...
return g(value-1) + 1
...
Die Funktion g() löst immer eine NameError-Ausnahme aus, da die Bindung des Namens g weder in ihrem lokalen Namensraum noch im Modulnamensraum vorhanden ist. Dies ist in der Praxis kein großes Problem (wie oft definiert man innere Funktionen auf diese Weise rekursiv?), aber es machte auch die Verwendung des lambda-Ausdrucks umständlicher, und das war ein praktisches Problem. In Code, der lambda verwendet, findet man oft lokale Variablen, die durch Übergabe als Standardwerte von Argumenten kopiert werden.
def find(self, name):
"Return list of any entries equal to 'name'"
L = filter(lambda x, name=name: x == name,
self.list_attribute)
return L
Die Lesbarkeit von Python-Code, der in einem stark funktionalen Stil geschrieben ist, leidet darunter erheblich.
Die bedeutendste Änderung in Python 2.1 ist die Hinzufügung von statischem Scoping zur Sprache, um dieses Problem zu beheben. Als erste Auswirkung ist das name=name Standardargument im obigen Beispiel nicht mehr notwendig. Vereinfacht gesagt, wenn einer Variablen innerhalb einer Funktion kein Wert zugewiesen wird (durch Zuweisung oder die def, class oder import-Anweisungen), werden Referenzen auf die Variable im lokalen Namensraum des umschließenden Scopes nachgeschlagen. Eine detailliertere Erklärung der Regeln und eine Zerlegung der Implementierung finden Sie in der PEP.
Diese Änderung kann zu Kompatibilitätsproblemen für Code führen, bei dem derselbe Variablenname sowohl auf Modulebene als auch als lokale Variable innerhalb einer Funktion verwendet wird, die weitere Funktionsdefinitionen enthält. Dies ist jedoch eher unwahrscheinlich, da solcher Code ohnehin schon ziemlich verwirrend zu lesen gewesen wäre.
Eine Nebenwirkung der Änderung ist, dass die Anweisungen from module import * und exec unter bestimmten Bedingungen innerhalb eines Funktions-Scopes illegal geworden sind. Das Python-Referenzhandbuch besagt schon immer, dass from module import * nur auf der obersten Ebene eines Moduls zulässig ist, aber der CPython-Interpreter hat dies bisher nie durchgesetzt. Als Teil der Implementierung verschachtelter Scopes muss der Compiler, der Python-Quellcode in Bytecodes umwandelt, anderen Code generieren, um auf Variablen in einem enthaltenden Scope zuzugreifen. from module import * und exec machen es dem Compiler unmöglich, dies herauszufinden, da sie Namen zum lokalen Namensraum hinzufügen, die zur Kompilierzeit unbekannt sind. Daher wird der Compiler, wenn eine Funktion Funktionsdefinitionen oder lambda-Ausdrücke mit freien Variablen enthält, dies durch Auslösen einer SyntaxError-Ausnahme kennzeichnen.
Um die vorherige Erklärung etwas klarer zu machen, hier ein Beispiel
x = 1
def f():
# The next line is a syntax error
exec 'x=2'
def g():
return x
Zeile 4, die die exec-Anweisung enthält, ist ein Syntaxfehler, da exec eine neue lokale Variable namens x definieren würde, deren Wert von g() abgerufen werden sollte.
Dies sollte keine große Einschränkung darstellen, da exec in den meisten Python-Codes selten verwendet wird (und wenn es verwendet wird, ist es oft ohnehin ein Zeichen für ein schlechtes Design).
Kompatibilitätsbedenken haben dazu geführt, dass verschachtelte Scopes schrittweise eingeführt wurden; in Python 2.1 sind sie nicht standardmäßig aktiviert, können aber innerhalb eines Moduls mithilfe einer `future`-Anweisung eingeschaltet werden, wie in PEP 236 beschrieben. (Siehe nächster Abschnitt für weitere Diskussionen zu PEP 236.) In Python 2.2 werden verschachtelte Scopes zur Standardeinstellung, und es wird keine Möglichkeit geben, sie zu deaktivieren, aber die Benutzer hatten die gesamte Lebensdauer von 2.1 Zeit, um alle Probleme zu beheben, die sich aus ihrer Einführung ergeben.
Siehe auch
- PEP 227 - Statically Nested Scopes
Geschrieben und implementiert von Jeremy Hylton.
PEP 236: __future__ Direktiven¶
Die Reaktion auf verschachtelte Scopes war weit verbreitete Besorgnis über die Gefahren, Code mit der Veröffentlichung von 2.1 zu brechen, und sie war stark genug, um die Pythoneers zu einem konservativeren Ansatz zu bewegen. Dieser Ansatz besteht darin, eine Konvention für die Aktivierung optionaler Funktionalität in Version N einzuführen, die in Version N+1 verpflichtend wird.
Die Syntax verwendet eine from...import-Anweisung unter Verwendung des reservierten Modulnamens __future__. Verschachtelte Scopes können durch die folgende Anweisung aktiviert werden
from __future__ import nested_scopes
Obwohl es wie eine normale import-Anweisung aussieht, ist es das nicht; es gibt strenge Regeln, wo eine solche `future`-Anweisung platziert werden kann. Sie kann nur am Anfang eines Moduls stehen und muss jeder Python-Code oder normale import-Anweisungen vorausgehen. Dies liegt daran, dass solche Anweisungen beeinflussen können, wie der Python-Bytecode-Compiler Code parst und Bytecode generiert, daher müssen sie jeder Anweisung vorausgehen, die zur Erzeugung von Bytecodes führt.
Siehe auch
- PEP 236 - Zurück zum
__future__ Geschrieben von Tim Peters, hauptsächlich implementiert von Jeremy Hylton.
PEP 207: Rich Comparisons¶
In früheren Versionen war Pythons Unterstützung für die Implementierung von Vergleichen für benutzerdefinierte Klassen und Erweiterungstypen recht einfach. Klassen konnten eine __cmp__()-Methode implementieren, der zwei Instanzen einer Klasse übergeben wurden und die nur 0 zurückgeben konnte, wenn sie gleich waren, oder +1 oder -1, wenn sie es nicht waren; die Methode konnte keine Ausnahme auslösen oder etwas anderes als einen booleschen Wert zurückgeben. Benutzer von Numeric Python fanden dieses Modell oft zu schwach und restriktiv, da es in numerischen Programmen, für die Numeric Python verwendet wird, nützlicher wäre, elementweise Vergleiche zweier Matrizen durchführen zu können, die eine Matrix mit den Ergebnissen eines bestimmten Vergleichs für jedes Element zurückgibt. Wenn die beiden Matrizen unterschiedliche Größen haben, muss der Vergleich eine Ausnahme auslösen können, um den Fehler zu signalisieren.
In Python 2.1 wurden Rich Comparisons hinzugefügt, um diesem Bedarf gerecht zu werden. Python-Klassen können jetzt individuell jeden der folgenden Operatoren überladen: <, <=, >, >=, == und !=. Die neuen magischen Methodennamen sind
Operation |
Methodenname |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
(Die magischen Methoden sind nach den entsprechenden Fortran-Operatoren .LT.. .LE., &c. benannt. Numerische Programmierer sind mit diesen Namen fast sicher bestens vertraut und werden sie leicht in Erinnerung behalten.)
Jede dieser magischen Methoden hat die Form method(self, other), wobei self das Objekt auf der linken Seite des Operators und other das Objekt auf der rechten Seite ist. Zum Beispiel führt der Ausdruck A < B zum Aufruf von A.__lt__(B).
Jede dieser magischen Methoden kann beliebig etwas zurückgeben: einen booleschen Wert, eine Matrix, eine Liste oder ein beliebiges anderes Python-Objekt. Alternativ kann sie eine Ausnahme auslösen, wenn der Vergleich unmöglich, inkonsistent oder anderweitig bedeutungslos ist.
Die eingebaute Funktion cmp(A,B) kann die Rich-Comparison-Mechanismen nutzen und akzeptiert nun ein optionales Argument, das angibt, welcher Vergleichsvorgang verwendet werden soll; dies wird als einer der Strings "<", "<=", ">", ">=", "==" oder "!=" angegeben. Wenn sie ohne das optionale dritte Argument aufgerufen wird, gibt cmp() nur -1, 0 oder +1 zurück, wie in früheren Versionen von Python; andernfalls ruft sie die entsprechende Methode auf und kann jedes Python-Objekt zurückgeben.
Es gibt auch entsprechende Änderungen, die für C-Programmierer von Interesse sind; es gibt einen neuen Slot tp_richcmp in Typobjekten und eine API zur Durchführung eines bestimmten Rich Comparisons. Ich werde die C-API hier nicht behandeln, sondern auf PEP 207 oder die C-API-Dokumentation von 2.1 verweisen, um die vollständige Liste der zugehörigen Funktionen zu erhalten.
Siehe auch
- PEP 207 - Rich Comparisons
Geschrieben von Guido van Rossum, stark basierend auf früheren Arbeiten von David Ascher, implementiert von Guido van Rossum.
PEP 230: Warning Framework¶
Im Laufe seiner 10-jährigen Existenz hat sich in Python eine Reihe von veralteten Modulen und Funktionen angesammelt. Es ist schwierig zu wissen, wann eine Funktion sicher entfernt werden kann, da keine Möglichkeit besteht zu wissen, wie viel Code sie verwendet – vielleicht hängen keine Programme von der Funktion ab, oder vielleicht viele. Um die Entfernung alter Funktionen auf strukturiertere Weise zu ermöglichen, wurde ein Warnsystem (Warning Framework) hinzugefügt. Wenn die Python-Entwickler eine Funktion entfernen wollen, wird sie in der nächsten Python-Version eine Warnung auslösen. Die nachfolgende Python-Version kann dann die Funktion entfernen, und die Benutzer hatten einen vollständigen Veröffentlichungszyklus Zeit, die Verwendungen der alten Funktion zu entfernen.
Python 2.1 fügt das Warnsystem für dieses Schema hinzu. Es fügt ein warnings-Modul hinzu, das Funktionen zum Ausgeben von Warnungen und zum Filtern von Warnungen, die Sie nicht angezeigt bekommen möchten, bereitstellt. Drittanbieter-Module können dieses System auch verwenden, um alte Funktionen zu verwerfen, die sie nicht mehr unterstützen möchten.
Zum Beispiel ist in Python 2.1 das Modul regex veraltet, sodass der Import eine Warnung ausgibt
>>> import regex
__main__:1: DeprecationWarning: the regex module
is deprecated; please use the re module
>>>
Warnungen können durch Aufruf der Funktion warnings.warn() ausgegeben werden
warnings.warn("feature X no longer supported")
Der erste Parameter ist die Warnmeldung; zusätzliche optionale Parameter können verwendet werden, um eine bestimmte Warnkategorie anzugeben.
Filter können hinzugefügt werden, um bestimmte Warnungen zu deaktivieren; ein regulärer Ausdruck kann auf die Nachricht oder den Modulnamen angewendet werden, um eine Warnung zu unterdrücken. Sie haben möglicherweise ein Programm, das das Modul regex verwendet und derzeit keine Zeit hat, es auf das Modul re umzustellen. Die Warnung kann durch Aufruf unterdrückt werden
import warnings
warnings.filterwarnings(action = 'ignore',
message='.*regex module is deprecated',
category=DeprecationWarning,
module = '__main__')
Dies fügt einen Filter hinzu, der nur auf Warnungen der Klasse DeprecationWarning angewendet wird, die im Modul __main__ ausgelöst werden, und wendet einen regulären Ausdruck an, um nur die Meldung über die Veralterung des Moduls regex abzugleichen, und bewirkt, dass solche Warnungen ignoriert werden. Warnungen können auch nur einmal ausgegeben werden, jedes Mal, wenn der fehlerhafte Code ausgeführt wird, oder in Ausnahmen umgewandelt werden, die dazu führen, dass das Programm stoppt (es sei denn, die Ausnahmen werden natürlich wie üblich abgefangen).
Es wurden auch Funktionen zur C-API von Python zum Ausgeben von Warnungen hinzugefügt; Einzelheiten finden Sie in PEP 230 oder in der C-API-Dokumentation von Python.
Siehe auch
- PEP 5 - Guidelines for Language Evolution
Geschrieben von Paul Prescod, um Verfahren für die Entfernung alter Funktionen aus Python festzulegen. Die in dieser PEP beschriebene Richtlinie wurde nicht offiziell übernommen, aber die endgültige Richtlinie wird wahrscheinlich nicht allzu sehr von Prescods Vorschlag abweichen.
- PEP 230 - Warning Framework
Geschrieben und implementiert von Guido van Rossum.
PEP 229: Neues Build-System¶
Beim Kompilieren von Python musste der Benutzer die Datei Modules/Setup bearbeiten, um verschiedene zusätzliche Module zu aktivieren. Die Standardmenge ist relativ klein und beschränkt auf Module, die auf den meisten Unix-Plattformen kompilieren. Das bedeutet, dass Python-Installationen auf Unix-Plattformen mit vielen zusätzlichen Features, insbesondere Linux, oft nicht alle nützlichen Module enthalten, die sie haben könnten.
Python 2.0 fügte die Distutils hinzu, eine Sammlung von Modulen zur Verteilung und Installation von Erweiterungen. In Python 2.1 werden die Distutils verwendet, um einen Großteil der Standardbibliothek von Erweiterungsmodulen zu kompilieren und automatisch zu erkennen, welche auf dem aktuellen Computer unterstützt werden. Es wird gehofft, dass dies Python-Installationen einfacher und funktionsreicher machen wird.
Anstatt die Datei Modules/Setup bearbeiten zu müssen, um Module zu aktivieren, wird ein setup.py-Skript im Stammverzeichnis der Python-Quellcode-Distribution zur Build-Zeit ausgeführt und versucht, zu ermitteln, welche Module durch Untersuchung der Module und Header-Dateien auf dem System aktiviert werden können. Wenn ein Modul in Modules/Setup konfiguriert ist, versucht das setup.py-Skript nicht, dieses Modul zu kompilieren, und greift auf den Inhalt der Datei Modules/Setup zurück. Dies bietet eine Möglichkeit, spezielle Kommandozeilen-Flags oder Bibliotheken anzugeben, die für eine bestimmte Plattform erforderlich sind.
In einer weiteren weitreichenden Änderung am Build-Mechanismus hat Neil Schemenauer die Dinge so umstrukturiert, dass Python nun eine einzige, nicht-rekursive Make-Datei verwendet, anstelle von Make-Dateien im Stammverzeichnis und in jedem der Unterverzeichnisse Python/, Parser/, Objects/ und Modules/. Dies beschleunigt das Erstellen von Python und macht das Ändern von Make-Dateien klarer und einfacher.
Siehe auch
- PEP 229 - Using Distutils to Build Python
Geschrieben und implementiert von A.M. Kuchling.
PEP 205: Weak References¶
Weak References, verfügbar über das Modul weakref, sind ein kleiner, aber nützlicher neuer Datentyp im Werkzeugkasten des Python-Programmierers.
Das Speichern einer Referenz auf ein Objekt (z.B. in einem Dictionary oder einer Liste) hat den Nebeneffekt, dass dieses Objekt dauerhaft am Leben gehalten wird. Es gibt einige spezifische Fälle, in denen dieses Verhalten unerwünscht ist, wobei Objekt-Caches der häufigste Fall sind und ein weiterer zirkuläre Referenzen in Datenstrukturen wie Bäumen.
Betrachten Sie zum Beispiel eine Memoizing-Funktion, die die Ergebnisse einer anderen Funktion f(x) zwischenspeichert, indem sie das Argument und das Ergebnis der Funktion in einem Dictionary speichert
_cache = {}
def memoize(x):
if _cache.has_key(x):
return _cache[x]
retval = f(x)
# Cache the returned object
_cache[x] = retval
return retval
Diese Version funktioniert für einfache Dinge wie Ganzzahlen, hat aber einen Nebeneffekt; das Dictionary _cache hält eine Referenz auf die Rückgabewerte, sodass diese nicht freigegeben werden, bis der Python-Prozess beendet ist und aufgeräumt wird. Dies ist bei Ganzzahlen nicht sehr bemerkbar, aber wenn f() ein Objekt oder eine Datenstruktur zurückgibt, die viel Speicherplatz beansprucht, kann dies ein Problem sein.
Weak References bieten eine Möglichkeit, einen Cache zu implementieren, der Objekte nicht länger am Leben hält als nötig. Wenn ein Objekt nur über Weak References zugänglich ist, wird das Objekt freigegeben und die Weak References zeigen nun an, dass das referenzierte Objekt nicht mehr existiert. Eine Weak Reference auf ein Objekt *obj* wird erstellt, indem wr = weakref.ref(obj) aufgerufen wird. Das referenzierte Objekt wird durch Aufruf der Weak Reference zurückgegeben, als ob es eine Funktion wäre: wr(). Es gibt das referenzierte Objekt oder None zurück, wenn das Objekt nicht mehr existiert.
Dies macht es möglich, eine Funktion memoize() zu schreiben, deren Cache keine Objekte am Leben hält, indem Weak References im Cache gespeichert werden.
_cache = {}
def memoize(x):
if _cache.has_key(x):
obj = _cache[x]()
# If weak reference object still exists,
# return it
if obj is not None: return obj
retval = f(x)
# Cache a weak reference
_cache[x] = weakref.ref(retval)
return retval
Das Modul weakref ermöglicht auch die Erstellung von Proxy-Objekten, die sich wie Weak References verhalten – ein Objekt, das nur durch Proxy-Objekte referenziert wird, wird freigegeben – aber anstatt einen expliziten Aufruf zum Abrufen des Objekts zu erfordern, leitet der Proxy alle Operationen transparent an das Objekt weiter, solange das Objekt noch existiert. Wenn das Objekt freigegeben wird, löst der Versuch, einen Proxy zu verwenden, eine weakref.ReferenceError-Ausnahme aus.
proxy = weakref.proxy(obj)
proxy.attr # Equivalent to obj.attr
proxy.meth() # Equivalent to obj.meth()
del obj
proxy.attr # raises weakref.ReferenceError
Siehe auch
- PEP 205 - Weak References
Geschrieben und implementiert von Fred L. Drake, Jr.
PEP 232: Funktionsattribute¶
In Python 2.1 können Funktionen nun beliebige Informationen zugewiesen bekommen. Leute benutzten oft Docstrings, um Informationen über Funktionen und Methoden zu speichern, da das Attribut __doc__ die einzige Möglichkeit war, Informationen an eine Funktion zu binden. Zum Beispiel werden im Zope Web Application Server Funktionen als sicher für den öffentlichen Zugriff gekennzeichnet, indem sie einen Docstring haben, und in John Aycocks SPARK-Parsing-Framework enthalten Docstrings Teile der BNF-Grammatik zum Parsen. Diese Überladung ist bedauerlich, da Docstrings eigentlich dazu gedacht sind, die Dokumentation einer Funktion zu enthalten; zum Beispiel bedeutet dies, dass Sie Funktionen für den privaten Gebrauch in Zope nicht ordnungsgemäß dokumentieren können.
Beliebige Attribute können nun auf Funktionen mit der regulären Python-Syntax gesetzt und abgerufen werden
def f(): pass
f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"
Das Dictionary, das Attribute enthält, kann als __dict__ der Funktion aufgerufen werden. Im Gegensatz zum __dict__-Attribut von Klasseninstanzen können Sie bei Funktionen tatsächlich ein neues Dictionary an __dict__ zuweisen, obwohl der neue Wert auf ein reguläres Python-Dictionary beschränkt ist; Sie können nicht schlau sein und es auf eine UserDict-Instanz oder ein beliebiges anderes Objekt setzen, das sich wie ein Mapping verhält.
Siehe auch
- PEP 232 - Function Attributes
Geschrieben und implementiert von Barry Warsaw.
PEP 235: Module auf Case-Insensitive Plattformen importieren¶
Einige Betriebssysteme haben Dateisysteme, die Case-Insensitive sind, MacOS und Windows sind die Hauptbeispiele; auf diesen Systemen ist es unmöglich, die Dateinamen FILE.PY und file.py zu unterscheiden, obwohl sie den Namen der Datei in ihrer ursprünglichen Groß-/Kleinschreibung speichern (sie sind auch Case-Preserving).
In Python 2.1 funktioniert die import-Anweisung, um auf Case-Insensitive-Plattformen Case-Sensitivität zu simulieren. Python sucht nun standardmäßig nach der ersten Case-Sensitiven Übereinstimmung und löst eine ImportError aus, wenn keine solche Datei gefunden wird, sodass import file kein Modul namens FILE.PY importiert. Case-Insensitive-Abgleich kann angefordert werden, indem die Umgebungsvariable PYTHONCASEOK gesetzt wird, bevor der Python-Interpreter gestartet wird.
PEP 217: Interactive Display Hook¶
Bei der interaktiven Verwendung des Python-Interpreters wird die Ausgabe von Befehlen mithilfe der eingebauten Funktion repr() angezeigt. In Python 2.1 kann die Variable sys.displayhook() auf ein aufrufbares Objekt gesetzt werden, das anstelle von repr() aufgerufen wird. Sie können es beispielsweise auf eine spezielle Pretty-Printing-Funktion setzen
>>> # Create a recursive data structure
... L = [1,2,3]
>>> L.append(L)
>>> L # Show Python's default output
[1, 2, 3, [...]]
>>> # Use pprint.pprint() as the display function
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3, <Recursion on list with id=135143996>]
>>>
Siehe auch
- PEP 217 - Display Hook für interaktive Nutzung
Geschrieben und implementiert von Moshe Zadka.
PEP 208: Neues Koerzionsmodell¶
Die Art und Weise, wie numerische Koerzion auf C-Ebene durchgeführt wird, wurde erheblich geändert. Dies wirkt sich nur auf die Autoren von C-Erweiterungen für Python aus und ermöglicht ihnen mehr Flexibilität beim Schreiben von Erweiterungstypen, die numerische Operationen unterstützen.
Erweiterungstypen können jetzt das Typ-Flag Py_TPFLAGS_CHECKTYPES in ihrer PyTypeObject-Struktur setzen, um anzuzeigen, dass sie das neue Koerzionsmodell unterstützen. In solchen Erweiterungstypen können die numerischen Slot-Funktionen nicht mehr davon ausgehen, dass sie zwei Argumente desselben Typs erhalten; stattdessen können sie zwei Argumente unterschiedlicher Typen erhalten und dann ihre eigene interne Koerzion durchführen. Wenn die Slot-Funktion einen Typ erhält, den sie nicht handhaben kann, kann sie das Fehlschlagen anzeigen, indem sie eine Referenz auf das Singleton-Wert Py_NotImplemented zurückgibt. Die numerischen Funktionen des anderen Typs werden dann versucht, und vielleicht können sie die Operation handhaben; wenn der andere Typ ebenfalls Py_NotImplemented zurückgibt, wird eine TypeError ausgelöst. In Python geschriebene numerische Methoden können ebenfalls Py_NotImplemented zurückgeben, wodurch der Interpreter so handelt, als ob die Methode nicht existieren würde (vielleicht wird eine TypeError ausgelöst, vielleicht werden die numerischen Methoden eines anderen Objekts versucht).
Siehe auch
- PEP 208 - Reworking the Coercion Model
Geschrieben und implementiert von Neil Schemenauer, stark basierend auf früheren Arbeiten von Marc-André Lemburg. Lesen Sie dies, um die Feinheiten zu verstehen, wie numerische Operationen nun auf C-Ebene verarbeitet werden.
PEP 241: Metadaten in Python-Paketen¶
Eine häufige Beschwerde von Python-Benutzern ist, dass es keinen einzigen Katalog aller existierenden Python-Module gibt. T. Middleton's Vaults of Parnassus unter www.vex.net/parnassus/ (eingestellt im Februar 2009, verfügbar im Internet Archive Wayback Machine) war der größte Katalog von Python-Modulen, aber die Registrierung von Software bei den Vaults war optional, und viele Leute machten sich nicht die Mühe.
Als erster kleiner Schritt zur Lösung des Problems wird Python-Software, die mit dem Distutils-Befehl sdist verpackt ist, eine Datei namens PKG-INFO enthalten, die Informationen über das Paket wie Name, Version und Autor enthält (Metadaten im Katalogisierungsterminologie). PEP 241 enthält die vollständige Liste der Felder, die in der Datei PKG-INFO enthalten sein können. Da die Leute begannen, ihre Software mit Python 2.1 zu verpacken, werden immer mehr Pakete Metadaten enthalten, was den Aufbau automatisierter Katalogisierungssysteme und Experimente damit ermöglicht. Mit den daraus gewonnenen Erfahrungen wird es vielleicht möglich sein, einen wirklich guten Katalog zu entwerfen und dann die Unterstützung dafür in Python 2.2 einzubauen. So könnten beispielsweise die Distutils-Befehle sdist und bdist_* eine Option upload unterstützen, die Ihr Paket automatisch auf einen Katalogserver hochlädt.
Sie können mit der Erstellung von Paketen, die PKG-INFO enthalten, beginnen, auch wenn Sie nicht Python 2.1 verwenden, da eine neue Version von Distutils für Benutzer früherer Python-Versionen veröffentlicht wird. Version 1.0.2 von Distutils enthält die in PEP 241 beschriebenen Änderungen sowie verschiedene Fehlerbehebungen und Verbesserungen. Sie wird von der Distutils SIG unter https://pythonlang.de/community/sigs/current/distutils-sig/ erhältlich sein.
Siehe auch
- PEP 241 - Metadaten für Python-Softwarepakete
Geschrieben und implementiert von A.M. Kuchling.
- PEP 243 - Mechanismus zum Hochladen von Modul-Repositories
Dieser Entwurf einer PEP, geschrieben von Sean Reifschneider, beschreibt einen vorgeschlagenen Mechanismus zum Hochladen von Python-Paketen auf einen zentralen Server.
Neue und verbesserte Module¶
Ka-Ping Yee steuerte zwei neue Module bei:
inspect.py, ein Modul zum Abrufen von Informationen über Live-Python-Code, undpydoc.py, ein Modul zur interaktiven Konvertierung von Docstrings in HTML oder Text. Als Bonus verwendetTools/scripts/pydoc, das jetzt automatisch installiert wird,pydoc.py, um die Dokumentation anhand eines Python-Modul-, Paket- oder Klassennamens anzuzeigen. Zum Beispiel zeigtpydoc xml.domFolgendes anPython Library Documentation: package xml.dom in xml NAME xml.dom - W3C Document Object Model implementation for Python. FILE /usr/local/lib/python2.1/xml/dom/__init__.pyc DESCRIPTION The Python mapping of the Document Object Model is documented in the Python Library Reference in the section on the xml.dom package. This package contains the following modules: ...
pydocenthält auch einen interaktiven Hilfe-Browser auf Tk-Basis.pydocmacht schnell süchtig; probieren Sie es aus!Zwei verschiedene Module für Unit-Tests wurden der Standardbibliothek hinzugefügt. Das Modul
doctest, beigesteuert von Tim Peters, bietet ein Test-Framework, das auf der Ausführung von eingebetteten Beispielen in Docstrings basiert und die Ergebnisse mit der erwarteten Ausgabe vergleicht. PyUnit, beigesteuert von Steve Purcell, ist ein Unit-Test-Framework, das von JUnit inspiriert wurde, welches wiederum eine Anpassung von Kent Becks Smalltalk-Test-Framework war. Weitere Informationen zu PyUnit finden Sie unter https://pyunit.sourceforge.net/.Das Modul
difflibenthält eine Klasse,SequenceMatcher, die zwei Sequenzen vergleicht und die Änderungen berechnet, die erforderlich sind, um eine Sequenz in die andere zu transformieren. Zum Beispiel kann dieses Modul verwendet werden, um ein Werkzeug ähnlich dem Unix-Programm diff zu schreiben, und tatsächlich demonstriert das BeispielprogrammTools/scripts/ndiff.py, wie ein solches Skript geschrieben wird.curses.panel, ein Wrapper für die Panel-Bibliothek, Teil von ncurses und von SYSV curses, wurde von Thomas Gellekum beigesteuert. Die Panel-Bibliothek bietet Fenstern die zusätzliche Funktion der Tiefe. Fenster können in der Tiefenordnung höher oder niedriger verschoben werden, und die Panel-Bibliothek ermittelt, wo sich Panels überlappen und welche Abschnitte sichtbar sind.Das PyXML-Paket hat seit Python 2.0 einige Veröffentlichungen durchlaufen, und Python 2.1 enthält eine aktualisierte Version des
xml-Pakets. Einige der bemerkenswerten Änderungen sind die Unterstützung für Expat 1.2 und spätere Versionen, die Fähigkeit von Expat-Parsern, Dateien in jeder von Python unterstützten Kodierung zu verarbeiten, sowie verschiedene Fehlerbehebungen für SAX, DOM und das Modulminidom.Ping steuerte auch einen weiteren Hook für die Behandlung von nicht abgefangenen Ausnahmen bei.
sys.excepthook()kann auf ein aufrufbares Objekt gesetzt werden. Wenn eine Ausnahme von keinemtry…except-Block abgefangen wird, wird die Ausnahme ansys.excepthook()übergeben, das dann tun kann, was es möchte. Auf der neunten Python-Konferenz demonstrierte Ping eine Anwendung für diesen Hook: das Drucken eines erweiterten Tracebacks, der nicht nur die Stack-Frames auflistet, sondern auch die Funktionsargumente und die lokalen Variablen für jeden Frame auflistet.Verschiedene Funktionen im Modul
time, wie z.B.asctime()undlocaltime(), erfordern ein Fließkommaargument, das die Zeit in Sekunden seit der Epoche enthält. Die häufigste Verwendung dieser Funktionen ist die Arbeit mit der aktuellen Zeit, daher wurde das Fließkommaargument optional gemacht; wenn kein Wert angegeben wird, wird die aktuelle Zeit verwendet. Zum Beispiel benötigen Log-Datei-Einträge normalerweise eine Zeichenkette, die die aktuelle Zeit enthält. In Python 2.1 kanntime.asctime()verwendet werden, anstelle des längerentime.asctime(time.localtime(time.time())), das zuvor erforderlich war.Diese Änderung wurde von Thomas Wouters vorgeschlagen und implementiert.
Das Modul
ftplibruft Dateien jetzt standardmäßig im passiven Modus ab, da der passive Modus eher von hinter einer Firewall funktioniert. Diese Anfrage kam aus dem Debian-Fehlerverfolgungssystem, da andere Debian-Paketeftplibverwenden, um Dateien abzurufen, und dann nicht von hinter einer Firewall funktionieren. Es wird als unwahrscheinlich angesehen, dass dies Probleme verursacht, da Netscape standardmäßig den passiven Modus verwendet und nur wenige Leute sich beschweren. Wenn der passive Modus jedoch für Ihre Anwendung oder Netzwerkkonfiguration ungeeignet ist, rufen Sieset_pasv(0)auf FTP-Objekten auf, um den passiven Modus zu deaktivieren.Die Unterstützung für den Zugriff auf Roh-Sockets wurde dem Modul
sockethinzugefügt, beigesteuert von Grant Edwards.Das Modul
pstatsenthält jetzt einen einfachen interaktiven Statistikbrowser zur Anzeige von Timing-Profilen für Python-Programme, der aufgerufen wird, wenn das Modul als Skript ausgeführt wird. Beigesteuert von Eric S. Raymond.Eine neue implementierungsabhängige Funktion,
sys._getframe([depth]), wurde hinzugefügt, um ein bestimmtes Frame-Objekt aus dem aktuellen Aufrufstapel zurückzugeben.sys._getframe()gibt den Frame an der Spitze des Aufrufstapels zurück; wenn das optionale Ganzzahlargument depth angegeben wird, gibt die Funktion den Frame zurück, der depth Aufrufe unterhalb der Spitze des Stapels liegt. Zum Beispiel gibtsys._getframe(1)das Frame-Objekt des Aufrufers zurück.Diese Funktion ist nur in CPython vorhanden, nicht in Jython oder der .NET-Implementierung. Verwenden Sie sie zum Debuggen und widerstehen Sie der Versuchung, sie in Produktionscode aufzunehmen.
Andere Änderungen und Korrekturen¶
Aufgrund des kürzeren Release-Zyklus wurden in Python 2.1 relativ wenige kleinere Änderungen vorgenommen. Eine Suche in den CVS-Änderungsprotokollen ergibt 117 angewendete Patches und 136 behobene Fehler; beide Zahlen sind wahrscheinlich Unterschätzungen. Einige der bemerkenswerteren Änderungen sind:
Ein spezialisierter Objektallokator ist jetzt optional verfügbar, der schneller sein sollte als die Systemfunktion
malloc()und weniger Speicheroverhead hat. Der Allokator verwendet die C-Funktionmalloc(), um große Speicherblöcke zu erhalten, und erfüllt dann kleinere Speicheranfragen aus diesen Blöcken. Er kann aktiviert werden, indem die Option--with-pymallocan das configure-Skript übergeben wird. Die Implementierungsdetails finden Sie unterObjects/obmalloc.c.Autoren von C-Erweiterungsmodulen sollten ihren Code mit aktiviertem Objektallokator testen, da einige fehlerhafte Codes brechen und zur Laufzeit zu Core-Dumps führen können. Es gibt eine Reihe von Speicherallokationsfunktionen in Pythons C-API, die bisher nur Aliase für die
malloc()undfree()der C-Bibliothek waren, was bedeutet, dass ein Fehler nicht bemerkbar war, wenn Sie versehentlich nicht übereinstimmende Funktionen aufgerufen haben. Wenn der Objektallokator aktiviert ist, sind diese Funktionen keine Aliase mehr vonmalloc()undfree(), und das Aufrufen der falschen Funktion zum Freigeben von Speicher führt zu einem Core-Dump. Zum Beispiel muss Speicher, der mitPyMem_Newalloziert wurde, mitPyMem_Del()freigegeben werden, nicht mitfree(). Einige mit Python mitgelieferte Module fielen dieser Regel zum Opfer und mussten behoben werden; zweifellos gibt es noch mehr Drittanbieter-Module, die das gleiche Problem haben werden.Der Objektallokator wurde von Vladimir Marangozov beigesteuert.
Die Geschwindigkeit von zeilenorientierter Datei-I/O wurde verbessert, da sich die Leute oft über deren mangelnde Geschwindigkeit beschweren und weil sie oft als naiver Benchmark verwendet wurde. Die Methode
readline()von Dateiobjekten wurde daher neu geschrieben, um sie viel schneller zu machen. Die genaue Geschwindigkeitssteigerung variiert je nach Plattform, abhängig davon, wie langsam diegetc()der C-Bibliothek war, aber sie liegt bei etwa 66 % und potenziell viel schneller auf einigen speziellen Betriebssystemen. Tim Peters hat einen Großteil des Benchmarkings und der Programmierung für diese Änderung durchgeführt, motiviert durch eine Diskussion in comp.lang.python.Ein neues Modul und eine neue Methode für Dateiobjekte wurden ebenfalls hinzugefügt, beigesteuert von Jeff Epler. Die neue Methode,
xreadlines(), ähnelt der vorhandenen integrierten Funktionxrange().xreadlines()gibt ein opakes Sequenzobjekt zurück, das nur durchlaufen werden kann, wobei bei jeder Iteration eine Zeile gelesen wird, aber nicht die gesamte Datei in den Speicher geladen wird, wie es die vorhandene Methodereadlines()tut. Sie würden es so verwenden:for line in sys.stdin.xreadlines(): # ... do something for each line ... ...
Eine ausführlichere Diskussion der Änderungen an der Zeilen-I/O finden Sie in der python-dev-Zusammenfassung vom 1. bis 15. Januar 2001 unter https://mail.python.org/pipermail/python-dev/2001-January/.
Eine neue Methode,
popitem(), wurde zu Dictionaries hinzugefügt, um ein destruktives Iterieren durch den Inhalt eines Dictionaries zu ermöglichen. Dies kann bei großen Dictionaries schneller sein, da keine Liste mit allen Schlüsseln oder Werten erstellt werden muss.D.popitem()entfernt ein beliebiges(key, value)-Paar aus dem DictionaryDund gibt es als 2-Tupel zurück. Dies wurde hauptsächlich von Tim Peters und Guido van Rossum implementiert, nach einem Vorschlag und einem vorläufigen Patch von Moshe Zadka.Module können jetzt steuern, welche Namen importiert werden, wenn
from module import *verwendet wird, indem sie ein Attribut__all__definieren, das eine Liste von Namen enthält, die importiert werden. Eine häufige Beschwerde ist, dass, wenn das Modul andere Module wiesysoderstringimportiert,from module import *diese zum Namensraum des importierenden Moduls hinzufügt. Um dies zu beheben, listen Sie einfach die öffentlichen Namen in__all__auf.# List public names __all__ = ['Database', 'open']
Eine strengere Version dieses Patches wurde zuerst von Ben Wolfson vorgeschlagen und implementiert, aber nach einiger Diskussion in python-dev wurde eine schwächere endgültige Version eingecheckt.
Die Anwendung von
repr()auf Zeichenketten verwendete zuvor Oktal-Escapes für nicht druckbare Zeichen; zum Beispiel war ein Zeilenumbruch'\012'. Dies war eine rudimentäre Spur von Pythons C-Abstammung, aber heute ist Oktal von sehr geringem praktischem Nutzen. Ka-Ping Yee schlug vor, Hex-Escapes anstelle von Oktal-Escapes zu verwenden und die Escapes\n,\t,\rfür die entsprechenden Zeichen zu verwenden und implementierte diese neue Formatierung.Syntaxfehler, die zur Kompilierungszeit erkannt werden, können jetzt Ausnahmen auslösen, die den Dateinamen und die Zeilennummer des Fehlers enthalten, ein angenehmer Nebeneffekt der Compiler-Reorganisation durch Jeremy Hylton.
C-Erweiterungen, die andere Module importieren, wurden geändert, um
PyImport_ImportModule()zu verwenden, was bedeutet, dass sie alle installierten Import-Hooks verwenden werden. Dies wird auch für Drittanbieter-Erweiterungen empfohlen, die ein anderes Modul aus C-Code importieren müssen.Die Größe der Unicode-Zeichendatenbank wurde dank Fredrik Lundh um weitere 340 KB reduziert.
Einige neue Ports wurden beigesteuert: MacOS X (von Steven Majewski), Cygwin (von Jason Tishler); RISCOS (von Dietmar Schwertberger); Unixware 7 (von Billy G. Allie).
Und dann gibt es die übliche Liste kleiner Fehlerbehebungen, kleiner Speicherlecks, Bearbeitungen von Docstrings und andere Tweaks, die zu lang sind, um sie einzeln aufzuführen; siehe die CVS-Protokolle für vollständige Details, wenn Sie sie wünschen.
Danksagungen¶
Der Autor möchte sich bei den folgenden Personen für ihre Vorschläge zu verschiedenen Entwürfen dieses Artikels bedanken: Graeme Cross, David Goodger, Jay Graves, Michael Hudson, Marc-André Lemburg, Fredrik Lundh, Neil Schemenauer, Thomas Wouters.