Was gibt es Neues in Python 3.1¶
- Autor:
Raymond Hettinger
Dieser Artikel erklärt die neuen Funktionen in Python 3.1 im Vergleich zu 3.0. Python 3.1 wurde am 27. Juni 2009 veröffentlicht.
PEP 372: Geordnete Dictionaries¶
Reguläre Python-Dictionaries iterieren über Schlüssel/Wert-Paare in beliebiger Reihenfolge. Im Laufe der Jahre haben eine Reihe von Autoren alternative Implementierungen geschrieben, die sich die Reihenfolge merken, in der die Schlüssel ursprünglich eingefügt wurden. Basierend auf den Erfahrungen aus diesen Implementierungen wurde eine neue Klasse collections.OrderedDict eingeführt.
Die API von OrderedDict ist im Wesentlichen dieselbe wie die von regulären Dictionaries, iteriert aber über Schlüssel und Werte in einer garantierten Reihenfolge, abhängig davon, wann ein Schlüssel zuerst eingefügt wurde. Wenn ein neuer Eintrag einen bestehenden Eintrag überschreibt, bleibt die ursprüngliche Einfügeposition unverändert. Das Löschen eines Eintrags und erneutes Einfügen verschiebt ihn ans Ende.
Die Standardbibliothek unterstützt nun die Verwendung von geordneten Dictionaries in mehreren Modulen. Das Modul configparser verwendet sie standardmäßig. Dies ermöglicht es, Konfigurationsdateien zu lesen, zu ändern und dann in ihrer ursprünglichen Reihenfolge zurückzuschreiben. Die Methode _asdict() für collections.namedtuple() gibt nun ein geordnetes Dictionary zurück, wobei die Werte in der gleichen Reihenfolge erscheinen wie die zugrunde liegenden Tupel-Indizes. Das Modul json wird um einen object_pairs_hook erweitert, der es ermöglicht, OrderedDicts durch den Decoder zu erstellen. Unterstützung wurde auch für Drittanbieter-Tools wie PyYAML hinzugefügt.
Siehe auch
- PEP 372 - Geordnete Dictionaries
PEP geschrieben von Armin Ronacher und Raymond Hettinger. Implementierung geschrieben von Raymond Hettinger.
Da ein geordnetes Dictionary seine Einfügungsreihenfolge beibehält, kann es in Verbindung mit Sortierung verwendet werden, um ein sortiertes Dictionary zu erstellen.
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
Die neuen sortierten Dictionaries behalten ihre Sortierreihenfolge bei, wenn Einträge gelöscht werden. Wenn jedoch neue Schlüssel hinzugefügt werden, werden die Schlüssel am Ende angehängt und die Sortierung wird nicht beibehalten.
PEP 378: Formatbezeichner für Tausendertrennzeichen¶
Die eingebaute Funktion format() und die Methode str.format() verwenden eine Minisprache, die nun eine einfache, nicht gebietsabhängige Möglichkeit zum Formatieren einer Zahl mit einem Tausendertrennzeichen enthält. Dies bietet eine Möglichkeit, die Ausgabe eines Programms zu humanisieren und sein professionelles Erscheinungsbild und seine Lesbarkeit zu verbessern.
>>> format(1234567, ',d')
'1,234,567'
>>> format(1234567.89, ',.2f')
'1,234,567.89'
>>> format(12345.6 + 8901234.12j, ',f')
'12,345.600000+8,901,234.120000j'
>>> format(Decimal('1234567.89'), ',f')
'1,234,567.89'
Die unterstützten Typen sind int, float, complex und decimal.Decimal.
Es finden Diskussionen darüber statt, wie alternative Trennzeichen wie Punkte, Leerzeichen, Apostrophe oder Unterstriche angegeben werden können. Gebietsabhängige Anwendungen sollten den vorhandenen n-Formatbezeichner verwenden, der bereits eine gewisse Unterstützung für Tausendertrennzeichen bietet.
Siehe auch
- PEP 378 - Formatbezeichner für Tausendertrennzeichen
PEP geschrieben von Raymond Hettinger und implementiert von Eric Smith und Mark Dickinson.
Andere Sprachänderungen¶
Einige kleinere Änderungen am Kern der Python-Sprache sind:
Verzeichnisse und ZIP-Archive, die eine Datei
__main__.pyenthalten, können jetzt direkt ausgeführt werden, indem ihr Name an den Interpreter übergeben wird. Das Verzeichnis/die ZIP-Datei wird automatisch als erster Eintrag in sys.path eingefügt. (Vorschlag und erster Patch von Andy Chu; überarbeiteter Patch von Phillip J. Eby und Nick Coghlan; bpo-1739468.)Der Typ
int()hat die Methodebit_lengtherhalten, die die Anzahl der Bits zurückgibt, die zur Darstellung seines Arguments in Binärform erforderlich sind.>>> n = 37 >>> bin(37) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(Beigesteuert von Fredrik Johansson, Victor Stinner, Raymond Hettinger und Mark Dickinson; bpo-3439.)
Die Felder in
format()-Strings können nun automatisch nummeriert werden.>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
Zuvor hätte der String nummerierte Felder wie folgt erfordert:
'Sir {0} of {1}'.(Beigesteuert von Eric Smith; bpo-5237.)
Die Funktion
string.maketrans()ist veraltet und wird durch neue statische Methoden ersetzt:bytes.maketrans()undbytearray.maketrans(). Diese Änderung löst die Verwirrung darüber, welche Typen vom Modulstringunterstützt wurden. Nun habenstr,bytesundbytearrayjeweils ihre eigenen maketrans und translate Methoden mit entsprechenden Zwischenübersetzungstabellen des richtigen Typs.(Beigesteuert von Georg Brandl; bpo-5675.)
Die Syntax der
with-Anweisung erlaubt nun mehrere Kontextmanager in einer einzigen Anweisung.>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '<critical>' in line: ... outfile.write(line)
Mit der neuen Syntax wird die Funktion
contextlib.nested()nicht mehr benötigt und ist nun veraltet.(Beigesteuert von Georg Brandl und Mattias Brändström; appspot-Problem 53094.)
round(x, n)gibt nun eine Ganzzahl zurück, wenn x eine Ganzzahl ist. Zuvor gab es einen Float zurück.>>> round(1123, -2) 1100
(Beigesteuert von Mark Dickinson; bpo-4707.)
Python verwendet nun den Algorithmus von David Gay, um die kürzeste Gleitkommadarstellung zu finden, die ihren Wert nicht ändert. Dies soll dazu beitragen, einige der Verwirrung bezüglich binärer Gleitkommazahlen zu mildern.
Die Bedeutung ist leicht an einer Zahl wie
1.1zu erkennen, die keine exakte Entsprechung in binären Gleitkommazahlen hat. Da es keine exakte Entsprechung gibt, ergibt ein Ausdruck wiefloat('1.1')den nächstgelegenen darstellbaren Wert, der0x1.199999999999ap+0in Hexadezimal oder1.100000000000000088817841970012523233890533447265625in Dezimal ist. Dieser nächstgelegene Wert wurde und wird weiterhin in nachfolgenden Gleitkomma-Berechnungen verwendet.Neu ist, wie die Zahl angezeigt wird. Früher verwendete Python einen einfachen Ansatz. Der Wert von
repr(1.1)wurde alsformat(1.1, '.17g')berechnet, was zu'1.1000000000000001'ausgewertet wurde. Der Vorteil der Verwendung von 17 Ziffern war, dass er auf den IEEE-754-Garantien beruhte, um sicherzustellen, dasseval(repr(1.1))exakt zu seinem ursprünglichen Wert zurückgerundet wurde. Der Nachteil war, dass viele Leute die Ausgabe verwirrend fanden (sie verwechselten intrinsische Einschränkungen der binären Gleitkommadarstellung mit einem Problem von Python selbst).Der neue Algorithmus für
repr(1.1)ist intelligenter und gibt'1.1'zurück. Im Wesentlichen durchsucht er alle äquivalenten String-Darstellungen (solche, die mit dem gleichen zugrundeliegenden Gleitkommawert gespeichert werden) und gibt die kürzeste Darstellung zurück.Der neue Algorithmus gibt tendenziell sauberere Darstellungen aus, wenn möglich, ändert aber nicht die zugrundeliegenden Werte. Daher gilt immer noch, dass
1.1 + 2.2 != 3.3, auch wenn die Darstellungen dies vermuten lassen.Der neue Algorithmus hängt von bestimmten Merkmalen der zugrundeliegenden Gleitkommaimplementierung ab. Wenn die erforderlichen Merkmale nicht gefunden werden, wird weiterhin der alte Algorithmus verwendet. Auch die Text-Pickle-Protokolle gewährleisten die plattformübergreifende Portabilität, indem sie den alten Algorithmus verwenden.
(Beigesteuert von Eric Smith und Mark Dickinson; bpo-1580)
Neue, verbesserte und veraltete Module¶
Eine Klasse
collections.Counterwurde hinzugefügt, um das bequeme Zählen eindeutiger Elemente in einer Sequenz oder einem Iterable zu unterstützen.>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
(Beigesteuert von Raymond Hettinger; bpo-1696199.)
Ein neues Modul,
tkinter.ttk, wurde hinzugefügt, um Zugriff auf die Tk thematisierte Widget-Sammlung zu erhalten. Die Grundidee von ttk ist es, den Code, der das Verhalten eines Widgets implementiert, vom Code, der sein Aussehen implementiert, so weit wie möglich zu trennen.(Beigesteuert von Guilherme Polo; bpo-2983.)
Die Klassen
gzip.GzipFileundbz2.BZ2Fileunterstützen nun das Kontextmanagement-Protokoll.>>> # Automatically close file after writing >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
(Beigesteuert von Antoine Pitrou.)
Das Modul
decimalunterstützt nun Methoden zur Erstellung eines Dezimalobjekts aus einem binärenfloat. Die Konvertierung ist exakt, kann aber manchmal überraschend sein.>>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625')
Das lange Dezimalergebnis zeigt den tatsächlichen binären Bruch, der für 1.1 gespeichert wird. Der Bruch hat viele Ziffern, da 1.1 nicht exakt in Binärform dargestellt werden kann.
(Beigesteuert von Raymond Hettinger und Mark Dickinson.)
Das Modul
itertoolshat zwei neue Funktionen erhalten. Die Funktionitertools.combinations_with_replacement()ist eine von vier Funktionen zur Erzeugung von Kombinatorik, einschließlich Permutationen und kartesischer Produkte. Die Funktionitertools.compress()ahmt ihr Namensvetter aus APL nach. Außerdem hat die vorhandene Funktionitertools.count()nun ein optionales Argument step und kann jede Art von zählbarer Sequenz akzeptieren, einschließlichfractions.Fractionunddecimal.Decimal.>>> [p+q for p,q in combinations_with_replacement('LOVE', 2)] ['LL', 'LO', 'LV', 'LE', 'OO', 'OV', 'OE', 'VV', 'VE', 'EE'] >>> list(compress(data=range(10), selectors=[0,0,1,1,0,1,0,1,0,0])) [2, 3, 5, 7] >>> c = count(start=Fraction(1,2), step=Fraction(1,6)) >>> [next(c), next(c), next(c), next(c)] [Fraction(1, 2), Fraction(2, 3), Fraction(5, 6), Fraction(1, 1)]
(Beigetragen von Raymond Hettinger.)
collections.namedtuple()unterstützt nun ein Schlüsselwortargument rename, das es ermöglicht, ungültige Feldnamen automatisch in Positionsnamen in der Form _0, _1 usw. umzuwandeln. Dies ist nützlich, wenn die Feldnamen von einer externen Quelle wie einer CSV-Kopfzeile, einer SQL-Feldliste oder Benutzereingaben stammen.>>> query = input() SELECT region, dept, count(*) FROM main GROUPBY region, dept >>> cursor.execute(query) >>> query_fields = [desc[0] for desc in cursor.description] >>> UserQuery = namedtuple('UserQuery', query_fields, rename=True) >>> pprint.pprint([UserQuery(*row) for row in cursor]) [UserQuery(region='South', dept='Shipping', _2=185), UserQuery(region='North', dept='Accounting', _2=37), UserQuery(region='West', dept='Sales', _2=419)]
(Beigesteuert von Raymond Hettinger; bpo-1818.)
Die Funktionen
re.sub(),re.subn()undre.split()akzeptieren nun einen Flags-Parameter.(Beigesteuert von Gregory Smith.)
Das Modul
loggingimplementiert nun eine einfache Klasselogging.NullHandlerfür Anwendungen, die keine Protokollierung verwenden, aber Bibliothekscode aufrufen, der dies tut. Das Einrichten eines Null-Handlers unterdrückt irreführende Warnungen wie "Keine Handler für den Logger foo gefunden".>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(Beigesteuert von Vinay Sajip; bpo-4384).
Das Modul
runpy, das den Kommandozeilenschalter-munterstützt, unterstützt nun die Ausführung von Paketen, indem es nach einem__main__-Untermodul sucht und dieses ausführt, wenn ein Paketname angegeben wird.(Beigesteuert von Andi Vajda; bpo-4195.)
Das Modul
pdbkann nun Quellcode abrufen und anzeigen, der überzipimport(oder einen anderen konformen PEP 302-Loader) geladen wurde.(Beigesteuert von Alexander Belopolsky; bpo-4201.)
functools.partial-Objekte können nun gepickelt werden.
(Vorgeschlagen von Antoine Pitrou und Jesse Noller. Implementiert von Jack Diederich; bpo-5228.)
Füge
pydoc-Hilfethemen für Symbole hinzu, damithelp('@')im interaktiven Umfeld wie erwartet funktioniert.(Beigesteuert von David Laban; bpo-4739.)
Das Modul
unittestunterstützt nun das Überspringen einzelner Tests oder Testklassen. Und es unterstützt das Markieren eines Tests als erwartetes Fehlschlagen, eines Tests, der bekanntermaßen fehlerhaft ist, aber nicht als Fehlschlag in einem TestResult gezählt werden soll.class TestGizmo(unittest.TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_gizmo_on_windows(self): ... @unittest.expectedFailure def test_gimzo_without_required_library(self): ...
Außerdem wurden Tests für Ausnahmen erweitert, um mit Kontextmanagern unter Verwendung der
with-Anweisung zu funktionieren.def test_division_by_zero(self): with self.assertRaises(ZeroDivisionError): x / 0
Darüber hinaus wurden mehrere neue Assertionsmethoden hinzugefügt, darunter
assertSetEqual(),assertDictEqual(),assertDictContainsSubset(),assertListEqual(),assertTupleEqual(),assertSequenceEqual(),assertRaisesRegexp(),assertIsNone()undassertIsNotNone().(Beigesteuert von Benjamin Peterson und Antoine Pitrou.)
Das Modul
iohat drei neue Konstanten für die Methodeseek():SEEK_SET,SEEK_CURundSEEK_END.Das Tupel
sys.version_infoist nun ein benanntes Tupel.>>> sys.version_info sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)
(Beigesteuert von Ross Light; bpo-4285.)
Die Module
nntplibundimaplibunterstützen nun IPv6.Das Modul
picklewurde für eine bessere Interoperabilität mit Python 2.x bei Verwendung von Protokoll 2 oder niedriger angepasst. Die Reorganisation der Standardbibliothek änderte die formale Referenz für viele Objekte. Zum Beispiel wird__builtin__.setin Python 2 alsbuiltins.setin Python 3 bezeichnet. Diese Änderung hat Bemühungen um den Datenaustausch zwischen verschiedenen Python-Versionen behindert. Aber jetzt, wenn Protokoll 2 oder niedriger ausgewählt wird, wird der Pickler automatisch die alten Python 2-Namen sowohl für das Laden als auch für das Speichern verwenden. Diese Neuzuordnung ist standardmäßig aktiviert, kann aber mit der Option fix_imports deaktiviert werden.>>> s = {1, 2, 3} >>> pickle.dumps(s, protocol=0) b'c__builtin__\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.' >>> pickle.dumps(s, protocol=0, fix_imports=False) b'cbuiltins\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.'
Eine unglückliche, aber unvermeidliche Nebenwirkung dieser Änderung ist, dass Protokoll 2-Pickles, die von Python 3.1 erstellt wurden, nicht mit Python 3.0 lesbar sind. Das neueste Pickle-Protokoll, Protokoll 3, sollte beim Migrieren von Daten zwischen Python 3.x-Implementierungen verwendet werden, da es nicht versucht, mit Python 2.x kompatibel zu bleiben.
(Beigesteuert von Alexandre Vassalotti und Antoine Pitrou, bpo-6137.)
Ein neues Modul,
importlib, wurde hinzugefügt. Es bietet eine vollständige, portable, reine Python-Referenzimplementierung derimport-Anweisung und ihres Gegenstücks, der Funktion__import__(). Es stellt einen erheblichen Fortschritt bei der Dokumentation und Definition der Aktionen dar, die während des Imports stattfinden.(Beigesteuert von Brett Cannon.)
Optimierungen¶
Umfangreiche Leistungsverbesserungen wurden hinzugefügt.
Die neue E/A-Bibliothek (wie in PEP 3116 definiert) war größtenteils in Python geschrieben und erwies sich schnell als problematischer Engpass in Python 3.0. In Python 3.1 wurde die E/A-Bibliothek vollständig in C neu geschrieben und ist je nach Aufgabe 2- bis 20-mal schneller. Die reine Python-Version ist weiterhin für Experimentierzwecke über das Modul
_pyioverfügbar.(Beigesteuert von Amaury Forgeot d’Arc und Antoine Pitrou.)
Eine Heuristik wurde hinzugefügt, damit Tupel und Dictionaries, die nur nicht nachverfolgbare Objekte enthalten, nicht vom Garbage Collector nachverfolgt werden. Dies kann die Größe von Sammlungen und damit den Overhead der Müllsammlung bei langlaufenden Programmen reduzieren, abhängig von ihrer spezifischen Verwendung von Datentypen.
(Beigesteuert von Antoine Pitrou, bpo-4688.)
Durch die Aktivierung einer Konfigurationsoption namens
--with-computed-gotosauf Compilern, die sie unterstützen (insbesondere: gcc, SunPro, icc), wird die Bytecode-Evaluationsschleife mit einem neuen Dispatch-Mechanismus kompiliert, der je nach System, Compiler und Benchmark Geschwindigkeitssteigerungen von bis zu 20% erzielt.(Beigesteuert von Antoine Pitrou zusammen mit einer Reihe anderer Teilnehmer, bpo-4753).
Die Dekodierung von UTF-8, UTF-16 und LATIN-1 ist nun zwei- bis viermal schneller.
(Beigesteuert von Antoine Pitrou und Amaury Forgeot d’Arc, bpo-4868.)
Das Modul
jsonverfügt nun über eine C-Erweiterung zur erheblichen Leistungssteigerung. Darüber hinaus wurde die API geändert, sodass JSON nur mitstrund nicht mitbytesarbeitet. Diese Änderung lässt das Modul eng mit der JSON-Spezifikation übereinstimmen, die in Bezug auf Unicode definiert ist.(Beigesteuert von Bob Ippolito und konvertiert zu Py3.1 von Antoine Pitrou und Benjamin Peterson; bpo-4136.)
Beim Entpickeln werden die Attributnamen von gepickelten Objekten nun interniert. Dies spart Speicher und ermöglicht kleinere Pickles.
(Beigesteuert von Jake McGuire und Antoine Pitrou; bpo-5084.)
IDLE¶
Das Menü "Format" von IDLE bietet nun eine Option zum Entfernen von nachgestellten Leerzeichen aus einer Quelldatei.
(Beigesteuert von Roger D. Serwy; bpo-5150.)
Build- und C-API-Änderungen¶
Änderungen am Build-Prozess von Python und an der C-API umfassen
Ganzzahlen werden nun intern entweder in Basis
2**15oder in Basis2**30gespeichert, wobei die Basis zur Erbauzeit bestimmt wird. Zuvor wurden sie immer in Basis2**15gespeichert. Die Verwendung von Basis2**30führt zu erheblichen Leistungsverbesserungen auf 64-Bit-Maschinen, aber die Benchmark-Ergebnisse auf 32-Bit-Maschinen sind gemischt. Daher ist die Standardeinstellung die Verwendung von Basis2**30auf 64-Bit-Maschinen und Basis2**15auf 32-Bit-Maschinen. Unter Unix gibt es eine neue Konfigurationsoption--enable-big-digits, die verwendet werden kann, um diese Standardeinstellung zu überschreiben.Abgesehen von den Leistungsverbesserungen sollte diese Änderung für Endbenutzer unsichtbar sein, mit einer Ausnahme: Zu Test- und Debugging-Zwecken gibt es ein neues
sys.int_info, das Informationen über das interne Format liefert, einschließlich der Anzahl der Bits pro Ziffer und der Größe in Bytes des C-Typs, der zum Speichern jeder Ziffer verwendet wird.>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(Beigetragen von Mark Dickinson; bpo-4258.)
Die Funktion
PyLong_AsUnsignedLongLong()behandelt nun einen negativen pylong, indem sieOverflowErroranstelle vonTypeErrorauslöst.(Beigetragen von Mark Dickinson und Lisandro Dalcrin; bpo-5175.)
Die Funktion
PyNumber_Int()ist veraltet. Verwenden Sie stattdessenPyNumber_Long().(Beigetragen von Mark Dickinson; bpo-4910.)
Eine neue Funktion
PyOS_string_to_double()wurde hinzugefügt, um die veralteten FunktionenPyOS_ascii_strtod()undPyOS_ascii_atof()zu ersetzen.(Beigetragen von Mark Dickinson; bpo-5914.)
PyCapsulewurde als Ersatz für diePyCObjectAPI hinzugefügt. Der Hauptunterschied besteht darin, dass der neue Typ eine klar definierte Schnittstelle für die Weitergabe von Typsicherheitsinformationen und eine einfachere Signatur für den Aufruf eines Destruktors aufweist. Der alte Typ hatte eine problematische API und ist nun veraltet.(Beigetragen von Larry Hastings; bpo-5630.)
Portierung auf Python 3.1¶
Dieser Abschnitt listet die zuvor beschriebenen Änderungen und andere Fehlerbehebungen auf, die möglicherweise Änderungen an Ihrem Code erfordern
Die neuen Zeichenkettendarstellungen von Gleitkommazahlen können bestehende Doctests brechen. Zum Beispiel
def e(): '''Compute the base of natural logarithms. >>> e() 2.7182818284590451 ''' return sum(1/math.factorial(x) for x in reversed(range(30))) doctest.testmod() ********************************************************************** Failed example: e() Expected: 2.7182818284590451 Got: 2.718281828459045 **********************************************************************
Die automatische Namenszuordnung im pickle-Modul für Protokoll 2 oder niedriger kann Python 3.1-Pickles in Python 3.0 unlesbar machen. Eine Lösung ist die Verwendung von Protokoll 3. Eine weitere Lösung ist das Setzen der Option fix_imports auf
False. Weitere Details finden Sie in der obigen Diskussion.