Was ist neu in Python 2.4¶
- Autor:
A.M. Kuchling
Dieser Artikel erklärt die neuen Funktionen in Python 2.4.1, veröffentlicht am 30. März 2005.
Python 2.4 ist eine mittelgroße Veröffentlichung. Sie führt nicht so viele Änderungen ein wie das radikale Python 2.2, aber mehr Funktionen als die konservative Veröffentlichung 2.3. Die bedeutendsten neuen Sprachfunktionen sind Funktionsdeklaratoren und Generator-Ausdrücke; die meisten anderen Änderungen betreffen die Standardbibliothek.
Laut den CVS-Änderungsprotokollen wurden zwischen Python 2.3 und 2.4 481 Patches angewendet und 502 Fehler behoben. Beide Zahlen sind wahrscheinlich Unterschätzungen.
Dieser Artikel versucht nicht, eine vollständige Spezifikation jeder einzelnen neuen Funktion zu liefern, sondern bietet eine kurze Einführung in jede Funktion. Für vollständige Details sollten Sie die Dokumentation für Python 2.4 konsultieren, wie z. B. die Python Library Reference und das Python Reference Manual. Oft werden Sie für Erklärungen zur Implementierung und zum Design auf die PEPs für eine bestimmte neue Funktion verwiesen.
PEP 218: Built-In Set Objects¶
Python 2.3 führte das Modul sets ein. C-Implementierungen von Set-Datentypen wurden nun als zwei neue eingebaute Typen, set(iterable) und frozenset(iterable), in den Python-Kern aufgenommen. Sie bieten schnelle Operationen für die Mitgliedschaftsprüfung, zum Entfernen von Duplikaten aus Sequenzen und für mathematische Operationen wie Vereinigungen, Schnitte, Differenzen und symmetrische Differenzen.
>>> a = set('abracadabra') # form a set from a string
>>> 'z' in a # fast membership testing
False
>>> a # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a) # convert back into a string
'arbcd'
>>> b = set('alacazam') # form a second set
>>> a - b # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # letters in both a and b
set(['a', 'c'])
>>> a ^ b # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])
>>> a.add('z') # add a new element
>>> a.update('wxy') # add multiple new elements
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x') # take one element out
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])
Der Typ frozenset() ist eine unveränderliche Version von set(). Da er unveränderlich und hashbar ist, kann er als Schlüssel für ein Wörterbuch oder als Element eines anderen Sets verwendet werden.
Das Modul sets verbleibt in der Standardbibliothek und kann nützlich sein, wenn Sie die Klassen Set oder ImmutableSet ableiten möchten. Es gibt derzeit keine Pläne, das Modul zu verwerfen.
Siehe auch
- PEP 218 - Hinzufügen eines integrierten Set-Objekttyps
Ursprünglich von Greg Wilson vorgeschlagen und letztendlich von Raymond Hettinger implementiert.
PEP 237: Vereinheitlichung von Long- und Integer-Zahlen¶
Der langwierige Übergangsprozess für diese PEP, der in Python 2.2 begann, macht in Python 2.4 einen weiteren Schritt. In 2.3 lösten bestimmte Integer-Operationen, die sich nach der Int/Long-Vereinheitlichung unterschiedlich verhalten würden, FutureWarning-Warnungen aus und lieferten auf 32 oder 64 Bits begrenzte Werte (abhängig von Ihrer Plattform). In 2.4 erzeugen diese Ausdrücke keine Warnung mehr und liefern stattdessen ein anderes Ergebnis, das normalerweise ein Long-Integer ist.
Die problematischen Ausdrücke sind hauptsächlich Linksshifts und lange Hexadezimal- und Oktalkonstanten. Zum Beispiel erzeugt 2 << 32 in 2.3 eine Warnung und wird auf 32-Bit-Plattformen als 0 ausgewertet. In Python 2.4 liefert dieser Ausdruck nun die korrekte Antwort, 8589934592.
Siehe auch
- PEP 237 - Vereinheitlichung von Long- und Integer-Zahlen
Ursprüngliche PEP von Moshe Zadka und GvR. Die Änderungen für 2.4 wurden von Kalle Svensson implementiert.
PEP 289: Generator Expressions¶
Die in Python 2.2 eingeführte Iterator-Funktion und das Modul itertools erleichtern das Schreiben von Programmen, die große Datensätze durchlaufen, ohne den gesamten Datensatz gleichzeitig im Speicher halten zu müssen. List Comprehensions passen nicht gut in dieses Bild, da sie ein Python-Listenobjekt mit allen Elementen erzeugen. Dies lädt zwangsläufig alle Objekte in den Speicher, was ein Problem sein kann, wenn Ihr Datensatz sehr groß ist. Beim Versuch, ein funktional gestaltetes Programm zu schreiben, wäre es natürlich, etwas wie Folgendes zu schreiben
links = [link for link in get_all_links() if not link.followed]
for link in links:
...
statt
for link in get_all_links():
if link.followed:
continue
...
Die erste Form ist prägnanter und vielleicht besser lesbar, aber wenn Sie mit einer großen Anzahl von Link-Objekten arbeiten, müssten Sie die zweite Form verwenden, um zu vermeiden, dass alle Link-Objekte gleichzeitig im Speicher gehalten werden.
Generator-Ausdrücke funktionieren ähnlich wie List Comprehensions, materialisieren aber nicht die gesamte Liste; stattdessen erstellen sie einen Generator, der Elemente einzeln zurückgibt. Das obige Beispiel könnte wie folgt geschrieben werden
links = (link for link in get_all_links() if not link.followed)
for link in links:
...
Generator-Ausdrücke müssen immer in Klammern geschrieben werden, wie im obigen Beispiel. Die Klammern, die einen Funktionsaufruf signalisieren, zählen ebenfalls. Wenn Sie also einen Iterator erstellen möchten, der sofort an eine Funktion übergeben wird, könnten Sie Folgendes schreiben
print sum(obj.count for obj in list_all_objects())
Generator-Ausdrücke unterscheiden sich in verschiedenen kleinen Punkten von List Comprehensions. Am bemerkenswertesten ist, dass die Schleifenvariable (obj im obigen Beispiel) außerhalb des Generator-Ausdrucks nicht zugänglich ist. List Comprehensions weisen der Variable ihren letzten Wert zu; zukünftige Versionen von Python werden dies ändern, sodass List Comprehensions in dieser Hinsicht mit Generator-Ausdrücken übereinstimmen.
Siehe auch
- PEP 289 - Generator Expressions
Vorgeschlagen von Raymond Hettinger und implementiert von Jiwon Seo mit ersten Bemühungen unter der Leitung von Hye-Shik Chang.
PEP 292: Einfachere String-Ersetzungen¶
Einige neue Klassen in der Standardbibliothek bieten einen alternativen Mechanismus für die Ersetzung von Variablen in Zeichenketten; dieser Stil der Ersetzung kann für Anwendungen besser geeignet sein, bei denen unerfahrene Benutzer Vorlagen bearbeiten müssen.
Die übliche Art, Variablen nach Namen zu ersetzen, ist der %-Operator
>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'
Beim Schreiben des Vorlagenstrings ist es leicht, das i oder s nach der schließenden Klammer zu vergessen. Dies ist kein großes Problem, wenn die Vorlage in einem Python-Modul liegt, da Sie den Code ausführen, einen ValueError "Unsupported format character" erhalten und das Problem beheben. Betrachten Sie jedoch eine Anwendung wie Mailman, bei der Vorlagenstrings oder Übersetzungen von Benutzern bearbeitet werden, die die Python-Sprache nicht kennen. Die Syntax des Formatstrings ist für solche Benutzer schwer zu erklären, und wenn sie einen Fehler machen, ist es schwierig, ihnen hilfreiches Feedback zu geben.
PEP 292 fügt dem Modul string eine Klasse Template hinzu, die $ zur Kennzeichnung einer Ersetzung verwendet
>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'
Wenn ein Schlüssel im Wörterbuch fehlt, löst die Methode substitute() einen KeyError aus. Es gibt auch eine Methode safe_substitute(), die fehlende Schlüssel ignoriert
>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'
Siehe auch
- PEP 292 - Simpler String Substitutions
Geschrieben und implementiert von Barry Warsaw.
PEP 318: Dekoratoren für Funktionen und Methoden¶
Python 2.2 erweiterte das Objektmodell von Python um statische Methoden und Klassenmethoden, erweiterte jedoch nicht die Python-Syntax, um eine neue Möglichkeit zur Definition von statischen oder Klassenmethoden bereitzustellen. Stattdessen mussten Sie eine def-Anweisung auf übliche Weise schreiben und die daraus resultierende Methode an eine Funktion staticmethod() oder classmethod() übergeben, die die Funktion als Methode des neuen Typs kapselt. Ihr Code würde so aussehen
class C:
def meth (cls):
...
meth = classmethod(meth) # Rebind name to wrapped-up class method
Wenn die Methode sehr lang war, war es leicht, die Aufrufe von classmethod() nach dem Funktionskörper zu übersehen oder zu vergessen.
Die Absicht war immer, eine Syntax hinzuzufügen, um solche Definitionen lesbarer zu machen, aber zur Zeit der Veröffentlichung von 2.2 war eine gute Syntax noch nicht offensichtlich. Heute ist eine gute Syntax *immer noch* nicht offensichtlich, aber Benutzer fragen nach einem einfacheren Zugang zu dieser Funktion; eine neue syntaktische Funktion wurde hinzugefügt, um diesem Bedürfnis gerecht zu werden.
Die neue Funktion heißt "Funktionsdeklaratoren". Der Name leitet sich von der Idee ab, dass classmethod(), staticmethod() und ähnliche Funktionen zusätzliche Informationen auf einem Funktionsobjekt speichern; sie *dekorieren* Funktionen mit weiteren Details.
Die Notation leiht sich von Java und verwendet das Zeichen '@' als Indikator. Mit der neuen Syntax würde das obige Beispiel geschrieben werden
class C:
@classmethod
def meth (cls):
...
Das @classmethod ist eine Kurzform für die Zuweisung meth=classmethod(meth). Allgemeiner gesagt, wenn Sie Folgendes haben
@A
@B
@C
def f ():
...
Es ist äquivalent zum folgenden Code vor der Deklaration
def f(): ...
f = A(B(C(f)))
Deklaratoren müssen auf der Zeile vor einer Funktionsdefinition stehen, ein Deklarator pro Zeile, und dürfen nicht auf derselben Zeile wie die def-Anweisung stehen, was bedeutet, dass @A def f(): ... illegal ist. Sie können nur Funktionsdefinitionen dekorieren, entweder auf Modulebene oder innerhalb einer Klasse; Klassendefinitionen können Sie nicht dekorieren.
Ein Deklarator ist nur eine Funktion, die die zu dekorierende Funktion als Argument nimmt und entweder dieselbe Funktion oder ein neues Objekt zurückgibt. Der Rückgabewert des Deklarators muss nicht aufrufbar sein (obwohl er es typischerweise ist), es sei denn, weitere Deklaratoren werden auf das Ergebnis angewendet. Es ist einfach, eigene Deklaratoren zu schreiben. Das folgende einfache Beispiel setzt nur ein Attribut auf dem Funktionsobjekt
>>> def deco(func):
... func.attr = 'decorated'
... return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>
Als etwas realistischeres Beispiel prüft der folgende Deklarator, ob das übergebene Argument ein Integer ist
def require_int (func):
def wrapper (arg):
assert isinstance(arg, int)
return func(arg)
return wrapper
@require_int
def p1 (arg):
print arg
@require_int
def p2(arg):
print arg*2
Ein Beispiel in PEP 318 enthält eine schickere Version dieser Idee, die es Ihnen ermöglicht, sowohl den erforderlichen Typ anzugeben als auch den zurückgegebenen Typ zu überprüfen.
Deklaratorfunktionen können Argumente annehmen. Wenn Argumente angegeben werden, wird Ihre Deklaratorfunktion nur mit diesen Argumenten aufgerufen und muss eine neue Deklaratorfunktion zurückgeben; diese Funktion muss eine einzelne Funktion aufnehmen und eine Funktion zurückgeben, wie zuvor beschrieben. Mit anderen Worten, @A @B @C(args) wird zu
def f(): ...
_deco = C(args)
f = A(B(_deco(f)))
Das Hinbekommen kann ein wenig anstrengend sein, ist aber nicht zu schwierig.
Eine kleine verwandte Änderung macht das Attribut func_name von Funktionen schreibbar. Dieses Attribut wird verwendet, um Funktionsnamen in Tracebacks anzuzeigen, daher sollten Deklaratoren den Namen jeder neu erstellten und zurückgegebenen Funktion ändern.
Siehe auch
- PEP 318 - Decorators for Functions, Methods and Classes
Geschrieben von Kevin D. Smith, Jim Jewett und Skip Montanaro. Mehrere Personen schrieben Patches zur Implementierung von Funktionsdeklaratoren, aber der Patch, der tatsächlich eingecheckt wurde, war Patch #979728, geschrieben von Mark Russell.
- https://wiki.python.org/moin/PythonDecoratorLibrary
Diese Wiki-Seite enthält mehrere Beispiele für Deklaratoren.
PEP 322: Umgekehrte Iteration¶
Eine neue eingebaute Funktion, reversed(seq), nimmt eine Sequenz und gibt einen Iterator zurück, der die Elemente der Sequenz in umgekehrter Reihenfolge durchläuft.
>>> for i in reversed(xrange(1,4)):
... print i
...
3
2
1
Im Vergleich zu erweiterten Slicings wie range(1,4)[::-1] ist reversed() leichter zu lesen, läuft schneller und verbraucht deutlich weniger Speicher.
Beachten Sie, dass reversed() nur Sequenzen akzeptiert, keine beliebigen Iteratoren. Wenn Sie einen Iterator umkehren möchten, konvertieren Sie ihn zuerst mit list() in eine Liste.
>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
... print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
...
Siehe auch
- PEP 322 - Reverse Iteration
Geschrieben und implementiert von Raymond Hettinger.
PEP 324: Neues subprocess-Modul¶
Die Standardbibliothek bietet eine Reihe von Möglichkeiten, einen Subprozess auszuführen, mit unterschiedlichen Funktionen und unterschiedlichen Komplexitätsstufen. os.system(command) ist einfach zu bedienen, aber langsam (es führt einen Shell-Prozess aus, der den Befehl ausführt) und gefährlich (man muss vorsichtig sein, die Metazeichen der Shell zu escapen). Das Modul popen2 bietet Klassen, die Standardausgabe und Standardfehlerausgabe des Subprozesses erfassen können, aber die Benennung ist verwirrend. Das Modul subprocess räumt dies auf und bietet eine einheitliche Schnittstelle, die alle benötigten Funktionen bietet.
Anstelle der Klassensammlung von popen2 enthält subprocess eine einzige Klasse namens subprocess.Popen, deren Konstruktor eine Reihe verschiedener Schlüsselwortargumente unterstützt.
class Popen(args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=False, shell=False,
cwd=None, env=None, universal_newlines=False,
startupinfo=None, creationflags=0):
args ist üblicherweise eine Sequenz von Strings, die die Argumente für das als Subprozess ausgeführte Programm sind. (Wenn das shell-Argument wahr ist, kann args ein String sein, der dann an die Shell zur Interpretation übergeben wird, genau wie os.system() es tut.)
stdin, stdout und stderr geben an, was die Eingabe-, Ausgabe- und Fehlerströme des Subprozesses sind. Sie können ein Datei-Objekt oder eine Datei-Deskriptor angeben, oder Sie können die Konstante subprocess.PIPE verwenden, um eine Pipe zwischen dem Subprozess und dem Elternteil zu erstellen.
Der Konstruktor hat eine Reihe von praktischen Optionen
close_fds fordert an, dass alle Datei-Deskriptoren vor dem Ausführen des Subprozesses geschlossen werden.
cwd gibt das Arbeitsverzeichnis an, in dem der Subprozess ausgeführt wird (standardmäßig das Arbeitsverzeichnis des Elternteils).
env ist ein Wörterbuch, das Umgebungsvariablen angibt.
preexec_fn ist eine Funktion, die aufgerufen wird, bevor das Kind gestartet wird.
universal_newlines öffnet die Eingabe- und Ausgabeströme des Kindes mit Pythons Funktion universal newlines.
Sobald Sie die Popen-Instanz erstellt haben, können Sie deren Methode wait() aufrufen, um zu warten, bis der Subprozess beendet ist, poll(), um zu prüfen, ob er beendet ist, ohne zu warten, oder communicate(data), um die Zeichenkette data an die Standardeingabe des Subprozesses zu senden. communicate(data) liest dann alle Daten, die der Subprozess an seine Standardausgabe oder Standardfehlerausgabe gesendet hat, und gibt ein Tupel (stdout_data, stderr_data) zurück.
call() ist eine Abkürzung, die ihre Argumente an den Popen-Konstruktor weitergibt, auf den Abschluss des Befehls wartet und den Statuscode des Subprozesses zurückgibt. Sie kann als sichereres Analogon zu os.system() dienen
sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
# Success
...
else:
# dpkg returned an error
...
Der Befehl wird ohne die Shell aufgerufen. Wenn Sie die Shell wirklich verwenden möchten, können Sie shell=True als Schlüsselwortargument hinzufügen und eine Zeichenkette anstelle einer Sequenz angeben
sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)
Die PEP nimmt verschiedene Beispiele für Shell- und Python-Code und zeigt, wie sie in Python-Code übersetzt würden, der subprocess verwendet. Das Lesen dieses Abschnitts der PEP wird dringend empfohlen.
Siehe auch
- PEP 324 - subprocess - Neues Prozessmodul
Geschrieben und implementiert von Peter Åstrand, mit Unterstützung von Fredrik Lundh und anderen.
PEP 327: Decimal Data Type¶
Python unterstützt seit jeher Gleitkommazahlen (FP), basierend auf dem zugrunde liegenden C double-Typ, als Datentyp. Während die meisten Programmiersprachen einen Gleitkommatyp anbieten, sind sich viele Menschen (sogar Programmierer) nicht bewusst, dass Gleitkommazahlen bestimmte Dezimalbrüche nicht genau darstellen. Der neue Typ Decimal kann diese Brüche bis zu einer vom Benutzer festgelegten Präzisionsgrenze genau darstellen.
Warum wird Decimal benötigt?¶
Die Einschränkungen ergeben sich aus der verwendeten Darstellung für Gleitkommazahlen. FP-Zahlen bestehen aus drei Komponenten
Das Vorzeichen, das positiv oder negativ ist.
Die Mantisse, eine einstellig binäre Zahl gefolgt von einem Bruchteil. Zum Beispiel ist
1.01in Binärschreibweise1 + 0/2 + 1/4oder 1.25 in Dezimalschreibweise.Der Exponent, der angibt, wo sich der Dezimalpunkt in der dargestellten Zahl befindet.
Zum Beispiel hat die Zahl 1.25 ein positives Vorzeichen, einen Mantissenwert von 1.01 (in Binär) und einen Exponenten von 0 (der Dezimalpunkt muss nicht verschoben werden). Die Zahl 5 hat das gleiche Vorzeichen und die gleiche Mantisse, aber der Exponent ist 2, da die Mantisse mit 4 (2 hoch Exponent 2) multipliziert wird; 1.25 * 4 ergibt 5.
Moderne Systeme bieten normalerweise Gleitkommastützen, die einem Standard namens IEEE 754 entsprechen. Der double-Typ von C wird normalerweise als 64-Bit-IEEE-754-Zahl implementiert, die 52 Bits für die Mantisse verwendet. Das bedeutet, dass Zahlen nur mit 52 Bit Präzision angegeben werden können. Wenn Sie versuchen, Zahlen darzustellen, deren Entwicklung sich endlos wiederholt, wird die Entwicklung nach 52 Bits abgeschnitten. Leider muss die meisten Software eine Ausgabe in Basis 10 erzeugen, und gängige Brüche in Basis 10 sind oft wiederholende Dezimalzahlen in Binär. Zum Beispiel ist 1.1 dezimal binär 1.0001100110011 ...; .1 = 1/16 + 1/32 + 1/256 plus eine unendliche Anzahl zusätzlicher Terme. IEEE 754 muss diese unendlich wiederholte Dezimalzahl nach 52 Ziffern abschneiden, daher ist die Darstellung leicht ungenau.
Manchmal sieht man diese Ungenauigkeit, wenn die Zahl ausgegeben wird
>>> 1.1
1.1000000000000001
Die Ungenauigkeit ist nicht immer sichtbar, wenn die Zahl ausgegeben wird, da die FP-zu-Dezimal-String-Konvertierung von der C-Bibliothek durchgeführt wird und die meisten C-Bibliotheken versuchen, sinnvolle Ausgaben zu erzeugen. Selbst wenn sie nicht angezeigt wird, ist die Ungenauigkeit immer noch vorhanden und nachfolgende Operationen können den Fehler verstärken.
Für viele Anwendungen spielt das keine Rolle. Wenn ich Punkte zeichne und sie auf meinem Monitor anzeige, ist der Unterschied zwischen 1.1 und 1.1000000000000001 zu klein, um sichtbar zu sein. Berichte beschränken die Ausgabe oft auf eine bestimmte Anzahl von Dezimalstellen, und wenn Sie die Zahl auf zwei, drei oder sogar acht Dezimalstellen runden, ist der Fehler nie offensichtlich. Für Anwendungen, bei denen es jedoch wichtig ist, ist es viel Arbeit, eigene benutzerdefinierte arithmetische Routinen zu implementieren.
Daher wurde der Typ Decimal erstellt.
Der Typ Decimal¶
Ein neues Modul, decimal, wurde in die Standardbibliothek von Python aufgenommen. Es enthält zwei Klassen, Decimal und Context. Decimal-Instanzen repräsentieren Zahlen, und Context-Instanzen werden verwendet, um verschiedene Einstellungen wie die Präzision und den Standard-Rundungsmodus zu kapseln.
Decimal-Instanzen sind unveränderlich, wie reguläre Python-Integer und FP-Zahlen; sobald sie erstellt wurden, können Sie den von einer Instanz dargestellten Wert nicht mehr ändern. Decimal-Instanzen können aus Integern oder Strings erstellt werden
>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")
Sie können auch Tupel mit dem Vorzeichen, der Mantisse als Tupel von Dezimalziffern und dem Exponenten bereitstellen
>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")
Vorsichtshinweis: Das Vorzeichenbit ist ein boolescher Wert, also ist 0 positiv und 1 negativ.
Die Konvertierung von Gleitkommazahlen stellt ein Problem dar: Soll die FP-Zahl, die 1.1 darstellt, in die Dezimalzahl von genau 1.1 umgewandelt werden oder in 1.1 plus alle Ungenauigkeiten, die eingeführt werden? Die Entscheidung war, das Problem zu umgehen und eine solche Konvertierung aus der API zu lassen. Stattdessen sollten Sie die Gleitkommazahl mit der gewünschten Präzision in einen String konvertieren und den String an den Decimal-Konstruktor übergeben
>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")
Sobald Sie Decimal-Instanzen haben, können Sie die üblichen mathematischen Operationen darauf ausführen. Eine Einschränkung: Potenzierung erfordert einen Integer-Exponenten
>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
...
decimal.InvalidOperation: x ** (non-integer)
Sie können Decimal-Instanzen mit Integern kombinieren, aber nicht mit Gleitkommazahlen
>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>
Decimal-Zahlen können mit den Modulen math und cmath verwendet werden, aber beachten Sie, dass sie sofort in Gleitkommazahlen umgewandelt werden, bevor die Operation durchgeführt wird, was zu einem möglichen Verlust an Präzision und Genauigkeit führt. Sie erhalten auch eine reguläre Gleitkommazahl zurück und nicht eine Decimal.
>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j
Decimal-Instanzen haben eine Methode sqrt(), die eine Decimal zurückgibt, aber wenn Sie andere Dinge wie trigonometrische Funktionen benötigen, müssen Sie diese selbst implementieren.
>>> d.sqrt()
Decimal("351364.1828820134592177245001")
Der Typ Context¶
Instanzen der Klasse Context kapseln mehrere Einstellungen für Dezimaloperationen
precist die Präzision, also die Anzahl der Dezimalstellen.roundinggibt den Rundungsmodus an. Das Moduldecimalhat Konstanten für die verschiedenen Möglichkeiten:ROUND_DOWN,ROUND_CEILING,ROUND_HALF_EVENund verschiedene andere.trapsist ein Wörterbuch, das angibt, was bei bestimmten Fehlerbedingungen passiert: entweder wird eine Ausnahme ausgelöst oder ein Wert zurückgegeben. Einige Beispiele für Fehlerbedingungen sind Division durch Null, Verlust der Präzision und Überlauf.
Es gibt einen Thread-lokalen Standardkontext, der durch Aufruf von getcontext() verfügbar ist; Sie können die Eigenschaften dieses Kontexts ändern, um die Standardpräzision, das Standard-Rundungsverfahren oder die Ausnahmebehandlung zu ändern. Das folgende Beispiel zeigt die Auswirkung der Änderung der Präzision des Standardkontexts
>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")
Die Standardaktion für Fehlerbedingungen ist wählbar; das Modul kann entweder einen speziellen Wert wie Unendlich oder Nicht-eine-Zahl zurückgeben, oder es können Ausnahmen ausgelöst werden
>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>
Die Instanz Context hat auch verschiedene Methoden zur Formatierung von Zahlen, wie to_eng_string() und to_sci_string().
Für weitere Informationen siehe die Dokumentation des Moduls decimal, die ein Schnelleinstiegs-Tutorial und eine Referenz enthält.
Siehe auch
- PEP 327 - Decimal Data Type
Geschrieben von Facundo Batista und implementiert von Facundo Batista, Eric Price, Raymond Hettinger, Aahz und Tim Peters.
- http://www.lahey.com/float.htm
Der Artikel verwendet Fortran-Code, um viele der Probleme zu veranschaulichen, die Ungenauigkeiten bei Gleitkommazahlen verursachen können.
- https://speleotrove.com/decimal/
Beschreibung einer dezimalbasierten Darstellung. Diese Darstellung wird als Standard vorgeschlagen und liegt der neuen Python-Dezimalzahl zugrunde. Ein Großteil dieses Materials wurde von Mike Cowlishaw, dem Designer der Rexx-Sprache, verfasst.
PEP 328: Mehrzeilige Importe¶
Eine Sprachänderung ist eine kleine syntaktische Anpassung, die darauf abzielt, den Import vieler Namen aus einem Modul zu erleichtern. In einer Anweisung from module import names ist names eine Sequenz von durch Kommas getrennten Namen. Wenn die Sequenz sehr lang ist, können Sie entweder mehrere Importe aus demselben Modul schreiben oder Backslashes verwenden, um Zeilenumbrüche zu escapen, wie hier
from SimpleXMLRPCServer import SimpleXMLRPCServer,\
SimpleXMLRPCRequestHandler,\
CGIXMLRPCRequestHandler,\
resolve_dotted_attribute
Die syntaktische Änderung in Python 2.4 erlaubt einfach, die Namen in Klammern zu setzen. Python ignoriert Zeilenumbrüche innerhalb eines geklammerten Ausdrucks, sodass die Backslashes nicht mehr benötigt werden
from SimpleXMLRPCServer import (SimpleXMLRPCServer,
SimpleXMLRPCRequestHandler,
CGIXMLRPCRequestHandler,
resolve_dotted_attribute)
Das PEP schlägt auch vor, dass alle import-Anweisungen absolute Imports sein sollen, mit einem führenden . Zeichen, um einen relativen Import anzuzeigen. Dieser Teil des PEP wurde nicht für Python 2.4 implementiert, wurde aber für Python 2.5 abgeschlossen.
Siehe auch
- PEP 328 - Imports: Mehrzeilig und Absolut/Relativ
Geschrieben von Aahz. Mehrzeilige Imports wurden von Dima Dorfman implementiert.
PEP 331: Locale-unabhängige Float/String-Konvertierungen¶
Das locale-Modul lässt Python-Software verschiedene Konvertierungen und Anzeigekonventionen auswählen, die für ein bestimmtes Land oder eine bestimmte Sprache lokalisiert sind. Das Modul hat jedoch darauf geachtet, die numerische Locale nicht zu ändern, da verschiedene Funktionen in Pythons Implementierung erforderten, dass die numerische Locale auf die 'C'-Locale eingestellt bleibt. Oft lag dies daran, dass der Code die atof()-Funktion der C-Bibliothek verwendete.
Das Nicht-Setzen der numerischen Locale bereitete jedoch Erweiterungen, die C-Bibliotheken von Drittanbietern nutzten, Schwierigkeiten, da diese nicht die korrekte Locale gesetzt hätten. Das motivierende Beispiel war GTK+, dessen Benutzeroberflächen-Widgets Zahlen nicht in der aktuellen Locale anzeigten.
Die im PEP beschriebene Lösung ist, drei neue Funktionen zur Python-API hinzuzufügen, die nur ASCII-Konvertierungen durchführen und die Locale-Einstellung ignorieren.
PyOS_ascii_strtod(str, ptr)undPyOS_ascii_atof(str, ptr)konvertieren beide einen String in einen C double.PyOS_ascii_formatd(buffer, buf_len, format, d)konvertiert einen double in einen ASCII-String.
Der Code für diese Funktionen stammt aus der GLib-Bibliothek (https://developer-old.gnome.org/glib/2.26/), deren Entwickler die relevanten Funktionen freundlicherweise unter Lizenz gestellt und der Python Software Foundation gespendet haben. Das locale-Modul kann nun die numerische Locale ändern, wodurch Erweiterungen wie GTK+ die korrekten Ergebnisse liefern können.
Siehe auch
- PEP 331 - Locale-unabhängige Float/String-Konvertierungen
Geschrieben von Christian R. Reis und implementiert von Gustavo Carneiro.
Andere Sprachänderungen¶
Hier sind alle Änderungen, die Python 2.4 an der Kernsprache Python vornimmt.
Dekoratoren für Funktionen und Methoden wurden hinzugefügt (PEP 318).
Integrierte
set()- undfrozenset()-Typen wurden hinzugefügt (PEP 218). Weitere neue eingebaute Funktionen sind die Funktionreversed(seq)(PEP 322).Generatorausdrücke wurden hinzugefügt (PEP 289).
Bestimmte numerische Ausdrücke geben nicht mehr nur Werte zurück, die auf 32 oder 64 Bits beschränkt sind (PEP 237).
Sie können nun Klammern um die Liste der Namen in einer
from module import names-Anweisung setzen (PEP 328).Die Methode
dict.update()akzeptiert nun die gleichen Argumentformen wie derdict-Konstruktor. Dies beinhaltet jede Zuordnung, jedes Iterable von Schlüssel/Wert-Paaren und Schlüsselwortargumente. (Beigetragen von Raymond Hettinger.)Die String-Methoden
ljust(),rjust()undcenter()nehmen nun ein optionales Argument zur Angabe eines Füllzeichens außer einem Leerzeichen entgegen. (Beigetragen von Raymond Hettinger.)Strings erhielten auch eine Methode
rsplit(), die wie die Methodesplit()funktioniert, aber vom Ende des Strings aus trennt. (Beigetragen von Sean Reifschneider.)>>> 'www.python.org'.split('.', 1) ['www', 'python.org'] 'www.python.org'.rsplit('.', 1) ['www.python', 'org']
Drei Schlüsselwortparameter, cmp, key und reverse, wurden zur Methode
sort()von Listen hinzugefügt. Diese Parameter vereinfachen einige gängige Verwendungen vonsort(). Alle diese Parameter sind optional.Für den Parameter cmp sollte der Wert eine Vergleichsfunktion sein, die zwei Parameter entgegennimmt und -1, 0 oder +1 zurückgibt, je nachdem, wie die Parameter verglichen werden. Diese Funktion wird dann zum Sortieren der Liste verwendet. Zuvor war dies der einzige Parameter, der an
sort()übergeben werden konnte.key sollte eine Ein-Parameter-Funktion sein, die ein Listenelement nimmt und einen Vergleichsschlüssel für das Element zurückgibt. Die Liste wird dann anhand der Vergleichsschlüssel sortiert. Das folgende Beispiel sortiert eine Liste ohne Berücksichtigung der Groß- und Kleinschreibung
>>> L = ['A', 'b', 'c', 'D'] >>> L.sort() # Case-sensitive sort >>> L ['A', 'D', 'b', 'c'] >>> # Using 'key' parameter to sort list >>> L.sort(key=lambda x: x.lower()) >>> L ['A', 'b', 'c', 'D'] >>> # Old-fashioned way >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower())) >>> L ['A', 'b', 'c', 'D']
Das letzte Beispiel, das den Parameter cmp verwendet, ist der alte Weg, eine sortierung ohne Berücksichtigung der Groß- und Kleinschreibung durchzuführen. Es funktioniert, ist aber langsamer als die Verwendung eines key-Parameters. Die Verwendung von key ruft die Methode
lower()einmal für jedes Element in der Liste auf, während die Verwendung von cmp sie zweimal für jeden Vergleich aufruft, sodass die Verwendung von key Aufrufe der Methodelower()spart.Für einfache Schlüsselfunktionen und Vergleichsfunktionen ist es oft möglich, eine
lambda-Expression zu vermeiden, indem stattdessen eine ungebundene Methode verwendet wird. Zum Beispiel ist die obige sortierung ohne Berücksichtigung der Groß- und Kleinschreibung am besten so geschrieben:>>> L.sort(key=str.lower) >>> L ['A', 'b', 'c', 'D']
Schließlich nimmt der Parameter reverse einen Booleschen Wert entgegen. Wenn der Wert wahr ist, wird die Liste in umgekehrter Reihenfolge sortiert. Anstelle von
L.sort(); L.reverse()können Sie nunL.sort(reverse=True)schreiben.Die Ergebnisse der Sortierung sind nun garantiert stabil. Das bedeutet, dass zwei Elemente mit gleichen Schlüsseln in der gleichen Reihenfolge zurückgegeben werden, in der sie eingegeben wurden. Sie können beispielsweise eine Liste von Personen nach Namen sortieren und dann die Liste nach Alter sortieren, was zu einer nach Alter sortierten Liste führt, in der Personen mit demselben Alter in der nach Namen sortierten Reihenfolge aufgeführt sind.
(Alle Änderungen an
sort()wurden von Raymond Hettinger beigesteuert.)Es gibt eine neue eingebaute Funktion
sorted(iterable), die wie die In-place-Methodelist.sort()funktioniert, aber in Ausdrücken verwendet werden kann. Die Unterschiede sind:die Eingabe kann ein beliebiges Iterable sein;
eine neu erstellte Kopie wird sortiert, wobei das Original unverändert bleibt; und
der Ausdruck gibt die neue sortierte Kopie zurück.
>>> L = [9,7,8,3,2,4,1,6,5] >>> [10+i for i in sorted(L)] # usable in a list comprehension [11, 12, 13, 14, 15, 16, 17, 18, 19] >>> L # original is left unchanged [9,7,8,3,2,4,1,6,5] >>> sorted('Monty Python') # any iterable may be an input [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y'] >>> # List the contents of a dict sorted by key values >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5) >>> for k, v in sorted(colormap.iteritems()): ... print k, v ... black 4 blue 2 green 3 red 1 yellow 5
(Beigetragen von Raymond Hettinger.)
Ganzzahloperationen lösen keine
OverflowWarningmehr aus. DieOverflowWarningwird in Python 2.5 verschwinden.Der Interpreter hat einen neuen Schalter,
-m, erhalten, der einen Namen entgegennimmt, nach dem entsprechenden Modul insys.pathsucht und das Modul als Skript ausführt. Sie können beispielsweise den Python-Profiler jetzt mitpython -m profileausführen. (Beigetragen von Nick Coghlan.)Die Funktionen
eval(expr, globals, locals)undexecfile(filename, globals, locals)sowie dieexec-Anweisung akzeptieren nun jeden Mapping-Typ für den Parameter locals. Zuvor musste dies ein reguläres Python-Dictionary sein. (Beigetragen von Raymond Hettinger.)Die eingebaute Funktion
zip()unditertools.izip()geben nun eine leere Liste zurück, wenn sie ohne Argumente aufgerufen werden. Zuvor lösten sie eineTypeError-Ausnahme aus. Dies macht sie besser für die Verwendung mit Argumentlisten variabler Länge geeignet.>>> def transpose(array): ... return zip(*array) ... >>> transpose([(1,2,3), (4,5,6)]) [(1, 4), (2, 5), (3, 6)] >>> transpose([]) []
(Beigetragen von Raymond Hettinger.)
Ein Fehler beim Importieren eines Moduls hinterlässt kein teilinitialisiertes Modulobjekt mehr in
sys.modules. Das verbleibende unvollständige Modulobjekt hätte weitere Importe desselben Moduls fälschlicherweise erfolgreich gemacht, was zu verwirrenden Fehlern geführt hätte. (Behoben von Tim Peters.)Noneist nun eine Konstante; Code, der einen neuen Wert an den NamenNonebindet, ist nun ein Syntaxfehler. (Beigetragen von Raymond Hettinger.)
Optimierungen¶
Die inneren Schleifen für Listen- und Tupelslicing wurden optimiert und laufen nun etwa ein Drittel schneller. Die inneren Schleifen für Dictionaries wurden ebenfalls optimiert, was zu Leistungssteigerungen für
keys(),values(),items(),iterkeys(),itervalues()unditeritems()führte. (Beigetragen von Raymond Hettinger.)Die Mechanismen zum Vergrößern und Verkleinern von Listen wurden auf Geschwindigkeit und Platzersparnis optimiert. Das Anhängen und Entnehmen von Elementen aus Listen ist nun schneller, da effizientere Code-Pfade und eine seltenere Nutzung von
realloc()des zugrunde liegenden Systems erfolgen. Listen-Comprehensions profitieren ebenfalls.list.extend()wurde ebenfalls optimiert und konvertiert sein Argument nicht mehr in eine temporäre Liste, bevor die Basisliste erweitert wird. (Beigetragen von Raymond Hettinger.)list(),tuple(),map(),filter()undzip()laufen nun mehrfach schneller mit Nicht-Sequenz-Argumenten, die eine__len__()-Methode bereitstellen. (Beigetragen von Raymond Hettinger.)Die Methoden
list.__getitem__(),dict.__getitem__()unddict.__contains__()werden nun alsmethod_descriptor-Objekte anstelle vonwrapper_descriptor-Objekten implementiert. Diese Zugriffsform verdoppelt ihre Leistung und macht sie besser für die Verwendung als Argumente für Funktionale geeignet:map(mydict.__getitem__, keylist). (Beigetragen von Raymond Hettinger.)Ein neuer Opcode,
LIST_APPEND, wurde hinzugefügt, der den generierten Bytecode für Listen-Comprehensions vereinfacht und diese um etwa ein Drittel beschleunigt. (Beigetragen von Raymond Hettinger.)Der Peephole-Bytecode-Optimierer wurde verbessert, um kürzeren, schnelleren Bytecode zu erzeugen; bemerkenswerterweise ist der resultierende Bytecode lesbarer. (Verbessert von Raymond Hettinger.)
String-Konkatenationen in Anweisungen der Form
s = s + "abc"unds += "abc"werden nun unter bestimmten Umständen effizienter durchgeführt. Diese Optimierung wird in anderen Python-Implementierungen wie Jython nicht vorhanden sein, daher sollten Sie sich nicht darauf verlassen; die Verwendung der Methodejoin()von Strings wird weiterhin empfohlen, wenn Sie eine große Anzahl von Strings effizient zusammenfügen möchten. (Beigetragen von Armin Rigo.)
Das Endergebnis der 2.4-Optimierungen ist, dass Python 2.4 den pystone-Benchmark etwa 5% schneller als Python 2.3 und 35% schneller als Python 2.2 ausführt. (pystone ist kein besonders guter Benchmark, aber er ist die am häufigsten verwendete Messung der Python-Leistung. Ihre eigenen Anwendungen können größere oder kleinere Vorteile von Python 2.4 aufweisen.)
Neue, verbesserte und veraltete Module¶
Wie üblich erhielt die Standardbibliothek von Python eine Reihe von Verbesserungen und Fehlerbehebungen. Hier ist eine Teilliste der bemerkenswertesten Änderungen, alphabetisch nach Modulnamen sortiert. Konsultieren Sie die Datei Misc/NEWS im Quellcode-Baum für eine vollständigere Liste der Änderungen oder schauen Sie sich die CVS-Protokolle für alle Details an.
Die Funktion
loop()des Modulsasyncoreverfügt nun über einen Parameter count, der es Ihnen ermöglicht, eine begrenzte Anzahl von Durchläufen durch die Abfrageschleife durchzuführen. Standardmäßig wird weiterhin endlos geschleift.Das Modul
base64hat nun eine vollständigere Unterstützung gemäß RFC 3548 für Base64-, Base32- und Base16-Kodierung und -Dekodierung, einschließlich optionaler Groß-/Kleinschreibung und optionaler alternativer Alphabete. (Beigetragen von Barry Warsaw.)Das Modul
bisecthat nun eine zugrundeliegende C-Implementierung für verbesserte Leistung. (Beigetragen von Dmitry Vasiliev.)Die Sammlung CJKCodecs von ostasiatischen Codecs, gepflegt von Hye-Shik Chang, wurde in 2.4 integriert. Die neuen Kodierungen sind:
Chinesisch (VR China): gb2312, gbk, gb18030, big5hkscs, hz
Chinesisch (ROC): big5, cp950
- Japanisch: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,
iso-2022-jp-1, iso-2022-jp-2, iso-2022-jp-3, iso-2022-jp-ext, iso-2022-jp-2004, shift-jis, shift-jisx0213, shift-jis-2004
Koreanisch: cp949, euc-kr, johab, iso-2022-kr
Einige andere neue Kodierungen wurden hinzugefügt: HP Roman8, ISO_8859-11, ISO_8859-16, PCTP-154 und TIS-620.
Die UTF-8- und UTF-16-Codecs gehen nun besser mit teilweisen Eingaben um. Zuvor versuchte die Klasse
StreamReader, mehr Daten zu lesen, was es unmöglich machte, die Dekodierung aus dem Stream fortzusetzen. Die Methoderead()gibt nun so viele Daten wie möglich zurück, und zukünftige Aufrufe setzen die Dekodierung dort fort, wo frühere aufgehört haben. (Implementiert von Walter Dörwald.)Es gibt ein neues Modul
collectionsfür verschiedene spezialisierte Container-Datentypen. Derzeit enthält es nur einen Typ,deque, eine doppelseitige Warteschlange, die das effiziente Hinzufügen und Entfernen von Elementen von beiden Enden unterstützt.>>> from collections import deque >>> d = deque('ghi') # make a new deque with three items >>> d.append('j') # add a new entry to the right side >>> d.appendleft('f') # add a new entry to the left side >>> d # show the representation of the deque deque(['f', 'g', 'h', 'i', 'j']) >>> d.pop() # return and remove the rightmost item 'j' >>> d.popleft() # return and remove the leftmost item 'f' >>> list(d) # list the contents of the deque ['g', 'h', 'i'] >>> 'h' in d # search the deque True
Mehrere Module, wie die Module
Queueundthreading, nutzen nuncollections.dequezur Leistungssteigerung. (Beigetragen von Raymond Hettinger.)Die Klassen
ConfigParserwurden geringfügig erweitert. Die Methoderead()gibt nun eine Liste der erfolgreich analysierten Dateien zurück, und die Methodeset()löst eineTypeErroraus, wenn ihr ein value-Argument übergeben wird, das keine Zeichenkette ist. (Beigetragen von John Belmonte und David Goodger.)Das Modul
cursesunterstützt nun die ncurses-Erweiterunguse_default_colors(). Auf Plattformen, auf denen das Terminal Transparenz unterstützt, ist es damit möglich, einen transparenten Hintergrund zu verwenden. (Beigetragen von Jörg Lehmann.)Das Modul
difflibenthält nun eine KlasseHtmlDiff, die eine HTML-Tabelle erstellt, die einen nebeneinanderliegenden Vergleich zweier Textversionen zeigt. (Beigetragen von Dan Gass.)Das Paket
emailwurde auf Version 3.0 aktualisiert, die verschiedene veraltete APIs entfernt hat und die Unterstützung für Python-Versionen vor 2.3 entfernt. Die Version 3.0 des Pakets verwendet einen neuen inkrementellen Parser für MIME-Nachrichten, der im Modulemail.FeedParserverfügbar ist. Der neue Parser erfordert nicht das Einlesen der gesamten Nachricht in den Speicher und löst keine Ausnahmen aus, wenn eine Nachricht fehlerhaft ist; stattdessen werden etwaige Probleme im Attributdefectder Nachricht aufgezeichnet. (Entwickelt von Anthony Baxter, Barry Warsaw, Thomas Wouters und anderen.)Das Modul
heapqwurde nach C portiert. Die daraus resultierende zehnfache Geschwindigkeitsverbesserung macht das Modul für die Verarbeitung großer Datenmengen geeignet. Darüber hinaus verfügt das Modul über zwei neue Funktionennlargest()undnsmallest(), die Heaps verwenden, um die N größten oder kleinsten Werte in einem Datensatz zu finden, ohne die Kosten einer vollständigen Sortierung. (Beigetragen von Raymond Hettinger.)Das Modul
httplibenthält nun Konstanten für HTTP-Statuscodes, die in verschiedenen HTTP-bezogenen RFC-Dokumenten definiert sind. Die Konstanten haben Namen wieOK,CREATED,CONTINUEundMOVED_PERMANENTLY; verwenden Sie pydoc, um eine vollständige Liste zu erhalten. (Beigetragen von Andrew Eland.)Das Modul
imaplibunterstützt nun den THREAD-Befehl von IMAP (beigesteuert von Yves Dionne) und die neuen Methodendeleteacl()undmyrights()(beigesteuert von Arnaud Mazin).Das Modul
itertoolserhielt eine Funktiongroupby(iterable[, *func*]). iterable ist etwas, das iteriert werden kann, um einen Strom von Elementen zurückzugeben, und der optionale Parameter func ist eine Funktion, die ein Element nimmt und einen Schlüsselwert zurückgibt; wenn er weggelassen wird, ist der Schlüssel einfach das Element selbst.groupby()gruppiert dann die Elemente in Untersequenzen, die übereinstimmende Schlüsselwerte haben, und gibt eine Reihe von 2-Tupeln zurück, die den Schlüsselwert und einen Iterator über die Untersequenz enthalten.Hier ist ein Beispiel zur Verdeutlichung. Die key-Funktion gibt einfach zurück, ob eine Zahl gerade oder ungerade ist, sodass das Ergebnis von
groupby()das Zurückgeben aufeinanderfolgender Läufe von ungeraden oder geraden Zahlen ist.>>> import itertools >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14] >>> for key_val, it in itertools.groupby(L, lambda x: x % 2): ... print key_val, list(it) ... 0 [2, 4, 6] 1 [7] 0 [8] 1 [9, 11] 0 [12, 14] >>>
groupby()wird typischerweise mit sortierter Eingabe verwendet. Die Logik fürgroupby()ist ähnlich dem Unix-Filteruniq, was ihn nützlich für die Eliminierung, Zählung oder Identifizierung von doppelten Elementen macht.>>> word = 'abracadabra' >>> letters = sorted(word) # Turn string into a sorted list of letters >>> letters ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r'] >>> for k, g in itertools.groupby(letters): ... print k, list(g) ... a ['a', 'a', 'a', 'a', 'a'] b ['b', 'b'] c ['c'] d ['d'] r ['r', 'r'] >>> # List unique letters >>> [k for k, g in groupby(letters)] ['a', 'b', 'c', 'd', 'r'] >>> # Count letter occurrences >>> [(k, len(list(g))) for k, g in groupby(letters)] [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
(Beigetragen von Hye-Shik Chang.)
itertoolserhielt auch eine Funktion namenstee(iterator, N), die N unabhängige Iteratoren zurückgibt, die iterator replizieren. Wenn N weggelassen wird, ist der Standardwert 2.>>> L = [1,2,3] >>> i1, i2 = itertools.tee(L) >>> i1,i2 (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>) >>> list(i1) # Run the first iterator to exhaustion [1, 2, 3] >>> list(i2) # Run the second iterator to exhaustion [1, 2, 3]
Beachten Sie, dass
tee()Kopien der vom Iterator zurückgegebenen Werte aufbewahren muss; im schlimmsten Fall muss es alle aufbewahren. Dies sollte daher mit Vorsicht verwendet werden, wenn der führende Iterator in einem langen Eingabestrom weit hinter dem nachfolgenden Iterator zurückbleiben kann. Wenn die Trennung groß ist, können Sie stattdessen auchlist()verwenden. Wenn die Iteratoren eng beieinander liegen, isttee()ideal. Mögliche Anwendungen sind Lesezeichen, Windowing oder Lookahead-Iteratoren. (Beigetragen von Raymond Hettinger.)Eine Reihe von Funktionen wurden dem Modul
localehinzugefügt, wie z.B.bind_textdomain_codeset()zur Angabe einer bestimmten Kodierung und eine Familie vonl*gettext()-Funktionen, die Nachrichten in der gewählten Kodierung zurückgeben. (Beigetragen von Gustavo Niemeyer.)Einige Schlüsselwortargumente wurden der Funktion
basicConfig()des Paketslogginghinzugefügt, um die Protokollkonfiguration zu vereinfachen. Das Standardverhalten ist, Nachrichten an Standard-Fehler zu protokollieren, aber verschiedene Schlüsselwortargumente können angegeben werden, um in eine bestimmte Datei zu protokollieren, das Protokollformat zu ändern oder die Protokollstufe festzulegen. Zum Beispielimport logging logging.basicConfig(filename='/var/log/application.log', level=0, # Log all messages format='%(levelname):%(process):%(thread):%(message)')
Weitere Ergänzungen zum Paket
loggingsind eine Komfortmethodelog(level, msg)sowie eine KlasseTimedRotatingFileHandler, die ihre Protokolldateien in zeitlichen Intervallen rotiert. Das Modul hatte bereitsRotatingFileHandler, das Protokolle rotierte, sobald die Datei eine bestimmte Größe überschritten hatte. Beide Klassen leiten sich von einer neuen KlasseBaseRotatingHandlerab, die zur Implementierung anderer rotierender Handler verwendet werden kann.(Änderungen implementiert von Vinay Sajip.)
Das Modul
marshalteilt nun internierte Strings beim Entpacken einer Datenstruktur. Dies kann die Größe bestimmter Pickle-Strings verringern, aber der Haupteffekt ist, dass.pyc-Dateien deutlich kleiner werden. (Beigetragen von Martin von Löwis.)Die Klasse
NNTPdes Modulsnntpliberhielt die Methodendescription()unddescriptions(), um Newsgroup-Beschreibungen für eine einzelne Gruppe oder für einen Bereich von Gruppen abzurufen. (Beigetragen von Jürgen A. Erhard.)Zwei neue Funktionen wurden dem Modul
operatorhinzugefügt:attrgetter(attr)unditemgetter(index). Beide Funktionen geben aufrufbare Objekte zurück, die ein einzelnes Argument nehmen und das entsprechende Attribut oder Element zurückgeben; diese aufrufbaren Objekte eignen sich hervorragend als Datenextraktoren, wenn sie mitmap()odersorted()verwendet werden. Zum Beispiel>>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)] >>> map(operator.itemgetter(0), L) ['c', 'd', 'a', 'b'] >>> map(operator.itemgetter(1), L) [2, 1, 4, 3] >>> sorted(L, key=operator.itemgetter(1)) # Sort list by second tuple item [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
(Beigetragen von Raymond Hettinger.)
Das Modul
optparsewurde auf verschiedene Weise aktualisiert. Das Modul übergibt seine Nachrichten nun übergettext.gettext(), wodurch es möglich ist, die Hilfe- und Fehlermeldungen von Optik zu internationalisieren. Hilfsmeldungen für Optionen können nun die Zeichenkette'%default'enthalten, die durch den Standardwert der Option ersetzt wird. (Beigetragen von Greg Ward.)Der Langzeitplan sieht vor, das Modul
rfc822in einer zukünftigen Python-Version zugunsten des Paketsemailzu verwerfen. Zu diesem Zweck wurde die Funktionemail.Utils.formatdateso geändert, dass sie als Ersatz fürrfc822.formatdate()verwendet werden kann. Möglicherweise möchten Sie neue E-Mail-Verarbeitungscodes mit diesem Ziel schreiben. (Änderung implementiert von Anthony Baxter.)Dem Modul
oswurde eine neue Funktionurandom(n)hinzugefügt, die eine Zeichenkette mit n zufälligen Bytes zurückgibt. Diese Funktion bietet Zugriff auf plattformspezifische Zufallsquellen wie/dev/urandomunter Linux oder die Windows CryptoAPI. (Beigetragen von Trevor Perrin.)Eine weitere neue Funktion:
os.path.lexists(path)gibt True zurück, wenn die durch path angegebene Datei existiert, unabhängig davon, ob es sich um einen symbolischen Link handelt oder nicht. Dies unterscheidet sich von der bestehenden Funktionos.path.exists(path), die False zurückgibt, wenn path ein Symlink ist, der auf ein nicht existierendes Ziel zeigt. (Beigetragen von Beni Cherniavsky.)Dem Modul
posix, das dem Moduloszugrunde liegt, wurde eine neue Funktiongetsid()hinzugefügt. (Beigetragen von J. Raynor.)Das Modul
poplibunterstützt nun POP über SSL. (Beigetragen von Hector Urtubia.)Das Modul
profilekann nun C-Erweiterungsfunktionen profilieren. (Beigetragen von Nick Bastin.)Das Modul
randomhat eine neue Methode namensgetrandbits(N), die eine Ganzzahl mit N Bits Länge zurückgibt. Die bestehende Methoderandrange()verwendet nun nach Möglichkeitgetrandbits(), wodurch die Erzeugung beliebig großer Zufallszahlen effizienter wird. (Beigetragen von Raymond Hettinger.)Die von dem Modul
reakzeptierte reguläre Ausdruckssprache wurde um einfache bedingte Ausdrücke erweitert, die als(?(group)A|B)geschrieben werden. group ist entweder eine numerische Gruppen-ID oder ein Gruppenname, der früher im Ausdruck mit(?P<group>...)definiert wurde. Wenn die angegebene Gruppe übereinstimmte, wird das reguläre Ausdrucksmuster A gegen die Zeichenkette getestet; wenn die Gruppe nicht übereinstimmte, wird stattdessen das Muster B verwendet. (Beigetragen von Gustavo Niemeyer.)Das Modul
reist dank massiver Arbeit von Gustavo Niemeyer nicht mehr rekursiv. In einer rekursiven regulären Ausdrucks-Engine verbrauchen bestimmte Muster eine große Menge an C-Stack-Speicherplatz, und es war möglich, den Stack zu überlaufen. Wenn Sie beispielsweise eine 30000 Byte lange Zeichenkette vona-Zeichen gegen den Ausdruck(a|b)+abgleichen, wurde pro Zeichen ein Stack-Frame verbraucht. Python 2.3 versuchte, auf Stack-Überläufe zu prüfen und eineRuntimeError-Ausnahme auszulösen, aber bestimmte Muster konnten die Prüfung umgehen, und wenn Sie Pech hatten, konnte Python abstürzen. Die reguläre Ausdrucks-Engine von Python 2.4 kann dieses Muster ohne Probleme abgleichen.Das Modul
signalführt nun eine engere Fehlerprüfung für die Parameter der Funktionsignal.signal()durch. Sie können beispielsweise keinen Handler für das SignalSIGKILLeinstellen; frühere Versionen von Python akzeptierten dies stillschweigend, aber 2.4 wird eineRuntimeError-Ausnahme auslösen.Dem Modul
socketwurden zwei neue Funktionen hinzugefügt.socketpair()gibt ein Paar verbundener Sockets zurück undgetservbyport(port)sucht den Servicenamen für eine gegebene Portnummer. (Beigetragen von Dave Cole und Barry Warsaw.)Die Funktion
sys.exitfunc()wurde veraltet erklärt. Code sollte das bestehende Modulatexitverwenden, das das korrekte Aufrufen mehrerer Exit-Funktionen handhabt. Schließlich wirdsys.exitfunc()eine rein interne Schnittstelle werden, die nur vonatexitaufgerufen wird.Das Modul
tarfilegeneriert standardmäßig GNU-Format-Tar-Dateien. (Beigetragen von Lars Gustäbel.)Das Modul
threadinghat nun eine elegant einfache Möglichkeit, thread-lokale Daten zu unterstützen. Das Modul enthält eine Klasselocal, deren Attributwerte für verschiedene Threads lokal sind.import threading data = threading.local() data.number = 42 data.url = ('www.python.org', 80)
Andere Threads können ihre eigenen Werte für die Attribute
numberundurlzuweisen und abrufen. Sie können vonlocalableiten, um Attribute zu initialisieren oder Methoden hinzuzufügen. (Beigetragen von Jim Fulton.)Das Modul
timeitdeaktiviert nun automatisch die periodische Speicherbereinigung während der Timing-Schleife. Diese Änderung macht aufeinanderfolgende Zeitmessungen besser vergleichbar. (Beigetragen von Raymond Hettinger.)Das Modul
weakrefunterstützt nun eine breitere Palette von Objekten, darunter Python-Funktionen, Klasseninstanzen, Sets, Frozensets, Deques, Arrays, Dateien, Sockets und reguläre Ausdrucksmusterobjekte. (Beigetragen von Raymond Hettinger.)Das Modul
xmlrpclibunterstützt nun eine Multi-Call-Erweiterung für die Übertragung mehrerer XML-RPC-Aufrufe in einem einzigen HTTP-Vorgang. (Beigetragen von Brian Quinlan.)Die Module
mpz,rotorundxreadlineswurden entfernt.
doctest¶
Das Modul doctest wurde dank Edward Loper und Tim Peters erheblich umgestaltet. Das Testen kann immer noch so einfach sein wie das Ausführen von doctest.testmod(), aber die Refactorings ermöglichen es, den Betrieb des Moduls auf verschiedene Weise anzupassen.
Die neue Klasse DocTestFinder extrahiert die Tests aus den Docstrings eines gegebenen Objekts.
def f (x, y):
""">>> f(2,2)
4
>>> f(3,2)
6
"""
return x*y
finder = doctest.DocTestFinder()
# Get list of DocTest instances
tests = finder.find(f)
Die neue Klasse DocTestRunner führt dann einzelne Tests aus und kann eine Zusammenfassung der Ergebnisse erstellen.
runner = doctest.DocTestRunner()
for t in tests:
tried, failed = runner.run(t)
runner.summarize(verbose=1)
Das obige Beispiel erzeugt die folgende Ausgabe.
1 items passed all tests:
2 tests in f
2 tests in 1 items.
2 passed and 0 failed.
Test passed.
DocTestRunner verwendet eine Instanz der Klasse OutputChecker, um die erwartete Ausgabe mit der tatsächlichen Ausgabe zu vergleichen. Diese Klasse nimmt eine Reihe verschiedener Flags entgegen, die ihr Verhalten anpassen; ambitionierte Benutzer können auch eine komplett neue Unterklasse von OutputChecker schreiben.
Der Standard-Output-Checker bietet eine Reihe nützlicher Funktionen. Beispielsweise passt mit dem Optionsflag doctest.ELLIPSIS ein Auslassungspunkt (...) in der erwarteten Ausgabe jede Teilzeichenkette an, wodurch es einfacher wird, Ausgaben zu handhaben, die sich in geringfügigen Details unterscheiden.
def o (n):
""">>> o(1)
<__main__.C instance at 0x...>
>>>
"""
Eine weitere spezielle Zeichenkette, <BLANKLINE>, passt auf eine leere Zeile.
def p (n):
""">>> p(1)
<BLANKLINE>
>>>
"""
Eine weitere neue Funktion ist die Erzeugung einer Diff-ähnlichen Anzeige der Ausgabe durch Angabe der Optionsflags doctest.REPORT_UDIFF (Unified Diffs), doctest.REPORT_CDIFF (Context Diffs) oder doctest.REPORT_NDIFF (Delta-Stil). Zum Beispiel.
def g (n):
""">>> g(4)
here
is
a
lengthy
>>>"""
L = 'here is a rather lengthy list of words'.split()
for word in L[:n]:
print word
Wenn die Tests der obigen Funktion mit angegebener doctest.REPORT_UDIFF ausgeführt werden, erhalten Sie die folgende Ausgabe.
**********************************************************************
File "t.py", line 15, in g
Failed example:
g(4)
Differences (unified diff with -expected +actual):
@@ -2,3 +2,3 @@
is
a
-lengthy
+rather
**********************************************************************
Build- und C-API-Änderungen¶
Einige der Änderungen am Build-Prozess von Python und an der C-API sind.
Drei neue Komfort-Makros wurden für gängige Rückgabewerte von Erweiterungsfunktionen hinzugefügt:
Py_RETURN_NONE,Py_RETURN_TRUEundPy_RETURN_FALSE. (Beigetragen von Brett Cannon.)Ein weiteres neues Makro,
Py_CLEAR, verringert die Referenzanzahl von obj und setzt obj auf den Null-Zeiger. (Beigetragen von Jim Fulton.)Eine neue Funktion,
PyTuple_Pack(N, obj1, obj2, ..., objN), erstellt Tupel aus einer variablen Liste von Python-Objekten. (Beigetragen von Raymond Hettinger.)Eine neue Funktion,
PyDict_Contains(d, k), implementiert schnelle Dictionary-Suchen, ohne Ausnahmen zu maskieren, die während des Suchvorgangs ausgelöst werden. (Beigetragen von Raymond Hettinger.)Das Makro Py_IS_NAN(X) gibt 1 zurück, wenn sein Float- oder Double-Argument X eine NaN ist. (Beigetragen von Tim Peters.)
C-Code kann unnötiges Locking vermeiden, indem die neue Funktion
PyEval_ThreadsInitialized()verwendet wird, um festzustellen, ob Thread-Operationen durchgeführt wurden. Wenn diese Funktion False zurückgibt, sind keine Lock-Operationen erforderlich. (Beigetragen von Nick Coghlan.)Eine neue Funktion,
PyArg_VaParseTupleAndKeywords(), ist identisch mitPyArg_ParseTupleAndKeywords(), nimmt aber eineva_listanstelle einer Anzahl von Argumenten. (Beigetragen von Greg Chapman.)Ein neues Methodenflag,
METH_COEXIST, ermöglicht es einer in Slots definierten Funktion, mit einerPyCFunctiongleichen Namens nebeneinander zu bestehen. Dies kann die Zugriffszeit für eine Methode wieset.__contains__()halbieren. (Beigetragen von Raymond Hettinger.)Python kann nun mit zusätzlichem Profiling für den Interpreter selbst erstellt werden, was als Hilfe für Entwickler des Python-Kerns gedacht ist. Durch Angabe von
--enable-profilingfür das configure-Skript können Sie den Interpreter mit gprof profilieren, und durch Angabe des Schalters--with-tscwird das Profiling mit dem Time-Stamp-Counter-Register des Pentium aktiviert. Beachten Sie, dass der Schalter--with-tscleicht irreführend benannt ist, da die Profiling-Funktion auch auf der PowerPC-Plattform funktioniert, obwohl diese Prozessorarchitektur dieses Register nicht "TSC-Register" nennt. (Beigetragen von Jeremy Hylton.)Der Typ
tracebackobjectwurde inPyTracebackObjectumbenannt.
Port-spezifische Änderungen¶
Der Windows-Port kompiliert nun unter MSVC++ 7.1 sowie Version 6. (Beigetragen von Martin von Löwis.)
Portierung auf Python 2.4¶
Dieser Abschnitt listet die zuvor beschriebenen Änderungen auf, die Änderungen an Ihrem Code erfordern könnten.
Linksschiebungen und hexadezimale/oktale Konstanten, die zu groß sind, lösen keine
FutureWarningmehr aus und geben keine auf 32 oder 64 Bits begrenzten Werte mehr zurück; stattdessen geben sie eine lange Ganzzahl zurück.Ganzzahloperationen lösen keine
OverflowWarningmehr aus. DieOverflowWarningwird in Python 2.5 verschwinden.Die eingebaute Funktion
zip()unditertools.izip()geben nun eine leere Liste zurück, anstatt eineTypeError-Ausnahme auszulösen, wenn sie ohne Argumente aufgerufen werden.Instanzen von
dateunddatetime, die vom Moduldatetimebereitgestellt werden, können nicht mehr verglichen werden. Zwei Instanzen verschiedener Klassen werden nun immer als ungleich angesehen, und relative Vergleiche (<,>) lösen eineTypeErroraus.dircache.listdir()gibt nun Ausnahmen an den Aufrufer weiter, anstatt leere Listen zurückzugeben.LexicalHandler.startDTD()erhielt früher die öffentlichen und System-IDs in der falschen Reihenfolge. Dies wurde korrigiert; Anwendungen, die von der falschen Reihenfolge abhingen, müssen korrigiert werden.fcntl.ioctl()gibt nun eine Warnung aus, wenn das Argument mutate weggelassen wird und dies relevant ist.Das Modul
tarfilegeneriert standardmäßig GNU-Format-Tar-Dateien.Das Auftreten eines Fehlers beim Importieren eines Moduls hinterlässt kein teilweise initialisiertes Modulobjekt mehr in
sys.modules.Noneist nun eine Konstante; Code, der der VariablenNoneeinen neuen Wert zuweist, ist nun ein Syntaxfehler.Die Funktion
signals.signal()löst nun eineRuntimeError-Ausnahme für bestimmte ungültige Werte aus; zuvor wurden diese Fehler stillschweigend akzeptiert. Sie können beispielsweise keinen Handler für das SignalSIGKILLeinstellen.
Danksagungen¶
Der Autor möchte sich bei den folgenden Personen für Vorschläge, Korrekturen und Unterstützung bei verschiedenen Entwürfen dieses Artikels bedanken: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.