Sind Wörterbücher bestellt in Python 3.6+?
Wörterbücher sind bestellt in Python 3.6 (unter der CPython-Implementierung zumindest) anders als in früheren Inkarnationen. Dies scheint eine wesentliche änderung, aber es ist nur ein kurzer Absatz in der Dokumentation. Es wird beschrieben, wie ein CPython-Implementierung detail eher als eine Sprache verfügen, sondern bedeutet auch dies kann als standard in die Zukunft.
Wie funktioniert der neue Wörterbuch-Implementierung eine bessere Leistung als die älteren bei gleichzeitiger Beibehaltung element um?
Hier ist der text aus der Dokumentation:
dict()
nutzt nun eine "kompakte" Darstellung Pionierarbeit von PyPy. Die Speicherauslastung der neuen dict() ist zwischen 20% und 25% kleiner im Vergleich zu Python 3.5. PEP 468 (Erhalt der Ordnung der **kwargs in einer Funktion.) umgesetzt wird dies. Die Reihenfolge-erhaltende Aspekt der neuen Implementierung ist als ein Implementierungsdetail und sollte nicht verlassen werden (dies könnte sich in Zukunft ändern, aber es wird gewünscht, diese neue dict-Umsetzung in die Sprache für ein paar releases, bevor die änderung der Sprache Skillung zu Mandat Auftrag-die Erhaltung der Semantik für alle gegenwärtigen und zukünftigen Python-Implementierungen; auch dies hilft bei der Erhaltung der rückwärts-Kompatibilität mit älteren Versionen der Sprache, wo zufällige iteration Bestellung ist noch immer in Kraft, z.B. Python 3.5). (Beigetragen von INADA Naoki in Problem 27350. Idee ursprünglich angeregt durch Raymond Hettinger.)
Update Dezember 2017: dict
s Beibehaltung einsetzen, um ist garantiert für Python 3.7
Beachten Sie, dass vor langer Zeit (2003), Perl-Implementierung entschieden, um hash-Tabellen (äquivalent zu Python dictionaries) nicht nur explizit ungeordnet, aber randomisierten, aus Gründen der Sicherheit (perldoc.perl.org/perlsec.html#Algorithmic-Complexity-Attacks). Also ich würde auf jeden Fall nicht damit rechnen, dass dieses "feature", denn wenn die Erfahrung der anderen kann ein Führer sein, es ist wahrscheinlich gilt Umgekehrt werden, irgendwann...
Wenn kwargs sollen bestellt werden (die nette Idee) und kwargs sind dict, nicht OrderedDict, dann denke ich, könnte man davon ausgehen, dass dict-Schlüssel bleiben wird, bestellt in der zukünftigen version von Python, trotz der Dokumentation etwas anderes sagt.
Nein, nicht von dieser Annahme ausgehen. Dies war ein Thema während dem schreiben der PEP, der definiert, um die Erhaltung feature von
**kwargs
und als solche die Formulierung ist Diplomatisch: **kwargs
in einer Funktion, die Signatur ist jetzt garantiert eine insertion-order-preserving Zuordnung. Sie haben den Begriff mapping, um Sie nicht zwingen einen anderen Implementierungen zu machen, die dict bestellt (und verwenden Sie ein OrderedDict
intern) und als ein Weg, um zu signalisieren, dass dies nicht soll, hängt von der Tatsache, dass die dict
ist nicht bestellt.Eine gute video-Erklärung von Raymond Hettinger
InformationsquelleAutor Chris_Rands | 2016-10-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie insertion bestellt[1]. Wie in der Python-3.6, für die CPython-Implementierung von Python, Wörterbücher erinnere mich an die Reihenfolge der Elemente eingefügt. Dies wird als eine Implementierung detail in Python-3.6; Sie verwenden müssen
OrderedDict
wenn Sie möchten, dass die insertion der Bestellung, dass die garantiert über andere Implementierungen von Python (und anderen bestellten Verhalten[1]).Als Python-3.7, ist dies nicht mehr ein Implementierungsdetail und stattdessen wird ein Sprach-feature. Von einem python-dev Nachricht von GvR:
Dies bedeutet einfach, dass darauf kann man sich verlassen. Andere Implementierungen von Python muss auch bieten eine insertion bestellt, Wörterbuch, wenn Sie es wünschen, um eine konforme Implementierung der Python-3.7.
Im wesentlichen durch den halten zwei arrays.
Dem ersten array,
dk_entries
, hält der Einträge (der TypPyDictKeyEntry
) das Wörterbuch in der Reihenfolge, wie Sie eingefügt wurden. Erhaltung der Ordnung wird erreicht, indem das eine append only-array, wobei neue Elemente immer eingesetzt am Ende (insertion order).Zweiten,
dk_indices
, hält die Indizes für diedk_entries
array (das heißt, Werte, die angeben, dass die position des entsprechenden Eintrags indk_entries
). Dieses array dient als der hash-Tabelle. Wenn ein Schlüssel gehasht ist es führt zu einer der Indizes gespeichert indk_indices
und der entsprechende Eintrag wird abgerufen durch die Indizierungdk_entries
. Da werden nur die Indizes gehalten werden, der den Typ dieses Arrays hängt von der Gesamt Größe des dictionary (im Bereich von Typint8_t
(1
byte)int32_t
/int64_t
(4
/8
bytes)32
/64
bit-builds)In der vorherigen Implementierung, eine sparse-array vom Typ
PyDictKeyEntry
und Größedk_size
zugeordnet werden musste; leider ist es auch zu viel leerer Platz, da das array nicht erlaubt war, mehr zu sein als2/3 * dk_size
voll aus performance-Gründen. (und den leeren Raum noch hattePyDictKeyEntry
Größe!).Dies ist nicht der Fall, da nur die erforderlich Einträge gespeichert sind (diejenigen, die eingefügt wurden) und ein sparse-array vom Typ
intX_t
(X
je nach dict-Größe)2/3 * dk_size
s voll gehalten wird. Der leere Raum geändert von TypPyDictKeyEntry
zuintX_t
.Also offensichtlich, die Schaffung eines sparse-Arrays des Typs
PyDictKeyEntry
ist viel mehr Speicher fordern als ein sparse-array für die Speicherungint
s.Können Sie sehen, das ganze Gespräch auf Python-Dev über diese Funktion, wenn Sie interessiert sind, ist es gut zu Lesen.
In dem ursprünglichen Vorschlag von Raymond Hettinger, eine Visualisierung von Datenstrukturen, die verwendet werden können, gesehen, erfasst den Kern der Idee.
So können Sie visuell sehen jetzt, in der ursprüngliche Vorschlag, eine Menge Platz ist im wesentlichen leer zu reduzieren Kollisionen und machen look-ups schneller. Mit dem neuen Konzept, reduzieren Sie den Speicherbedarf durch verschieben der Kargheit, wo es wirklich erforderlich, in den Indizes.
[1]: ich sage "insertion bestellt" und nicht "bestellt", da mit der Existenz von OrderedDict, "bestellt", schlägt weiter Verhalten, dass die
dict
Objekt nicht. OrderedDicts reversibel sind, bieten, um sensible Methoden und, vor allem, bieten Sie eine um-sensive Gleichheit tests (==
,!=
).dict
s derzeit bieten keine dieser Verhaltensmuster/- Methoden.[2]: Der neue Wörterbuch-Implementierungen bessere Speicher weisen durch mehr entwickelt, kompakt; das ist der größte Vorteil hier. Geschwindigkeit klug, der Unterschied ist nicht so drastisch, es gibt Orte, wo das neue dict führen könnten leichte Regressionen ( Schlüssel-lookups, zum Beispiel ), während in anderen (iteration und Größenänderung in den Sinn kommen) eine Leistungssteigerung vorhanden sein sollten.
Insgesamt ist die Leistung des Wörterbuches, vor allem in real-life-Situationen, verbessert aufgrund der Kompaktheit eingeführt.
entries
Liste geändert? oder ist ein Leerzeichen eingehalten? oder ist es komprimiert von Zeit zu Zeit?Wenn ein Element entfernt wird, wird der entsprechende index wird ersetzt durch
DKIX_DUMMY
mit einem Wert von-2
und der Eintrag in derentry
array ersetzt durchNULL
, beim einfügen durchgeführt wird, werden die neuen Werte werden an die entries-array, Noch nicht in der Lage zu erkennen, doch aber ziemlich sicher, wenn die Indizes füllt sich jenseits der2/3
Schwelle Größenänderung durchgeführt. Dies kann dazu führen, zu schrumpfen statt zu wachsen, wenn vieleDUMMY
Einträge vorhanden sind.NÖ, die werden nur tatsächliche regression, die ich gesehen habe ist auf dem tracker in einem Nachricht von Victor. Andere als die microbenchmark, ich habe gesehen, kein anderes Problem/Meldung eine ernsthafte Geschwindigkeit Unterschied in der real-life-Arbeit Lasten. Es gibt Orte, wo das neue dict führen könnten leichte Regressionen (key-Suchvorgänge, zum Beispiel), während Sie in anderen (iteration und Größenänderung in den Sinn kommen) eine Leistungssteigerung vorhanden wäre.
Korrektur auf die Größenänderung Teil: Wörterbücher nicht der Größe, wenn Sie Elemente löschen, Sie neu zu berechnen, wenn Sie Sie wieder einsetzen. Also, wenn ein dict erstellt mit
d = {i:i for i in range(100)}
und Sie.pop
alle Elemente w/o einfügen, die Größe ändern nicht. Wenn Sie hinzufügen, um Sie wiederd[1] = 1
die entsprechende Größe berechnet wird, und der dict ändert.Ich bin mir ziemlich sicher, dass es bleiben wird. Die Sache ist, und der Grund, warum ich änderte meine Antwort zu entfernen, Decke Aussagen über '
dict
bestellt',dict
s sind nicht geordnet im SinneOrderedDict
s sind. Das Bemerkenswerte Problem ist die Gleichheit.dict
s haben, um unempfindlich==
,OrderedDict
s haben, um den empfindlichen. DumpingOrderedDict
s und änderndicts
jetzt haben, um sensible Vergleiche könnte dazu führen, eine Menge von Bruch, die in altem code. Ich vermute, dass die einzige Sache, die möglicherweise eine änderung derOrderedDict
s ist seine Umsetzung.InformationsquelleAutor Jim Fasarakis Hilliard
Unten ist die Beantwortung der ersten Frage:
Ich denke, dieser Satz aus der Dokumentation ist eigentlich genug, um Ihre Frage zu beantworten
dict
wird nicht ausdrücklich gedacht, um eine geordnete collection, also, wenn Sie wollen, um konsistent bleiben und sich nicht auf einen Nebeneffekt der neuen Implementierung, die Sie sollten stick mitOrderedDict
.Machen Sie Ihren code zukunftssicher 🙂
Es gibt eine Debatte darüber, dass hier.
EDIT: Python 3.7 halten dies als eine Funktion sehen
Ich bin mir nicht sicher über das edit-VORBEHALT; da die Garantie gilt nur für Python-3.7, ich nehme an, der Rat für Python 3.6 ist unverändert, d.h. dicts sind bestellt in CPython aber zählen Sie nicht auf es
InformationsquelleAutor Maresh
Update:
Guido van Rossum angekündigt auf der mailing-Liste , wie der Python-3.7
dict
s in allen Python-Implementierungen müssen bewahren, insertion um.Ich denke, OrderedDict wird nicht überflüssig sein, weil es die
move_to_end
Methode und Ihre Gleichheit ist, um sensible: docs.python.org/3/library/.... Siehe Hinweis auf Jim Fasarakis Hilliard Antwort.siehe Jim ' s Antwort, und diese F& stackoverflow.com/questions/50872498/...
Wenn Sie möchten, dass Ihr code ausgeführt werden, der das gleiche auf 2.7 und 3.6/3.7+ verwenden, benötigen Sie OrderedDict
Wahrscheinlich wird es eine "UnorderedDict" bald für Leute, die gerne ärger Ihrer dicts aus Gründen der Sicherheit ;p
InformationsquelleAutor fjsj