Warum ist die Tupel schneller als Liste in Python?
Habe ich gerade gelesen, in "Dive into Python", dass "Tupel sind schneller als Listen".
Tupel unveränderlich ist, und die Liste ist änderbar, aber ich verstehe nicht ganz, warum Tupel schneller ist.
Jemand hat einen performance test dazu?
- Bitte Bearbeiten Sie die Frage und füge einen link zu dem Rahmen, wo Sie immer sind diesem Anspruch aus. Ich werde sogar freundlich sein und es Ihnen geben, so dass Sie nicht haben, um gehen auf der Suche für Sie es erneut: diveintopython3.org/native-datatypes.html#tuples
- Ich lese die PDF-version, damit ich nicht über den link. Vielen Dank :), werde ich es hinzufügen, in der Frage
- Auf einer anderen Anmerkung, du hast Recht, in Frage zu stellen Ansprüche wie diese. Der Python-interpreter änderungen in jedem release; performance-Ansprüche sollte immer empirisch validiert, die auf Ihre eigene Plattform vor, die Ihnen folgten. wiki.python.org/moin/PythonSpeed/PerformanceTips Alec Thomas, die Antwort ist ein leuchtendes Beispiel dafür, wie dies schnell zu tun für dich in der Zukunft. Siehe auch das timeit-Dokumentation: docs.python.org/library/timeit.html
- Lesen Sie jetzt, danke 🙂
InformationsquelleAutor Vimvq1987 | 2010-07-27
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Berichtet die "speed of construction" - Verhältnis gilt nur für Konstante Tupel (diejenigen, deren Elemente ausgedrückt werden, indem Literale). Sorgfältig beobachten (und wiederholen Sie die auf Ihrem Computer-Sie müssen nur geben Sie die Befehle in einer shell/Befehls-Fenster!)...:
Habe ich nicht die Messungen auf 3.0, weil ich natürlich nicht herum-es ist völlig veraltet und es gibt absolut kein Grund zu halten Sie herum, seit 3.1 ist überlegen in jeder Hinsicht (Python 2.7, wenn Sie aktualisieren können, um es Maßnahmen, wie Sie fast 20% schneller als 2.6 in jeder Aufgabe-und 2,6, wie Sie sehen, ist schneller als 3.1 -- so, wenn Sie Pflege ernst über die Leistung, Python 2.7 ist wirklich der einzige Veröffentlichung, die Sie sollten gehen für!).
Trotzdem, der entscheidende Punkt hier ist, dass, in jeder Python-Version, bauen Sie eine Liste von Konstanten Literale ist etwa die gleiche Geschwindigkeit, oder etwas langsamer, als es aus der Werte verwiesen wird, die von Variablen; aber Tupel Verhalten sich sehr unterschiedlich -- Gebäude ein Tupel aus Konstanten Literale ist in der Regel drei mal so schnell wie der Bau von Werte verwiesen wird, die von Variablen! Sie Fragen sich vielleicht, wie das sein kann, richtig?-)
Antwort: ein Tupel aus Konstanten Literale können leicht identifiziert werden, durch die der Python-compiler als eine, unveränderliche Konstante-literal selbst: so ist es im wesentlichen genauso gebaut wurde, einmal, wenn der compiler wandelt den Quellcode in Bytecode, und verstaut in der "Konstanten-Tabelle" der jeweiligen Funktion oder Modul. Wenn diese bytecodes ausführen, die Sie gerade benötigen, um wieder die vordefinierte Konstante Tupel-hey presto!-)
Dieser einfachen Optimierung nicht angewandt werden können, zu Listen, da eine Liste ist ein veränderliches Objekt, so ist es wichtig, dass, wenn der gleiche Ausdruck wie
[1, 2, 3]
führt zweimal (in einer Schleife -- dietimeit
- Modul macht die Schleife auf Ihrem Namen;-), ein frisches, neues list-Objekt ist konstruiert, jedes mal wieder neu-und das Baugewerbe (wie der Bau eines Tupels, wenn der compiler nicht trivial identifizieren es als compile-time-Konstante und unveränderliche Objekt) braucht eine Weile.Dass gesagt wird, die Tupel-Konstruktion (wenn beide Konstruktionen haben tatsächlich
auftreten) immer noch etwa doppelt so schnell als Liste Bau-und , dass Diskrepanz kann erklärt werden durch die Tupel ist die schiere Einfachheit, die andere Antworten haben, die immer wieder genannt. Aber, dass Einfachheit nicht berücksichtigt, für eine Beschleunigung von sechs mal oder mehr, als Sie beobachten, wenn Sie nur vergleichen Sie den Bau von Listen und Tupeln mit einfachen Konstanten Literale als Ihre Einzelteile!_)
Alex gab eine großartige Antwort, aber ich werde versuchen zu erweitern auf ein paar Dinge finde ich erwähnenswert. Etwaige performance-Unterschiede sind in der Regel klein und Umsetzung spezifischer: so nicht Wetten der farm auf Sie.
In CPython, Tupel gespeichert sind in einem einzigen block des Speichers, also die Schaffung eines neuen Tupel beinhaltet, im schlimmsten Fall ein einziger Anruf, um Speicher zuzuweisen. Listen zugeordnet sind, in zwei Blöcke: die Feste mit allen Python-Objekt information, und eine variable-sized-block für die Daten. Das ist Teil der Grund, warum die Schaffung eines Tupel schneller ist, aber es wahrscheinlich erklärt sich auch der leichte Unterschied in der Indexierung Geschwindigkeit, wie es ist eine weniger Zeiger zu Folgen.
Gibt es auch Optimierungen in CPython zu reduzieren, Speicher-Zuweisungen: de-Liste zugewiesen-Objekte gespeichert werden auf eine freie Liste, so dass Sie wiederverwendet werden kann, aber die Zuteilung nicht-leere Liste benötigt noch eine Zuweisung von Speicher für die Daten. Tupel gespeichert sind, auf den 20 freien Listen für unterschiedliche sortierte Tupel, so dass die Zuteilung einer kleinen Tupel wird oft benötigt keine memory allocation Anrufe zu allen.
Optimierungen wie diese sind hilfreich in der Praxis, aber Sie kann auch machen es riskant ist, hängen zu sehr auf die Ergebnisse der 'timeit' und sind natürlich völlig unterschiedlich aus, wenn Sie sich bewegen, um so etwas wie IronPython, wo der Speicher Zuweisung funktioniert ganz anders.
PyObject * PyBLAH_GetItem(PyObject *op, Py_ssize_t i) {return ((PyBLAHObject *)op) -> ob_item[i];}
ob_item
ist ein array an das Ende der Struktur. In einer Listeob_item
ist ein Zeiger auf ein array. Der C-code für den Zugriff auf ein element entweder array ist identisch, aber bei einer Liste gibt es eine extra memory read zum abrufen des Werts des Zeiger.PyObject * ob_item[1];
listobject.h hatPyObject ** ob_item;
Mit der Kraft des
timeit
- Modul, können Sie oft beheben Sie performance-Fragen Sie sich selbst:Dies zeigt, dass die Tupel ist vernachlässigbar schneller als Liste für die iteration. Ich bekomme ähnliche Ergebnisse für Indizierung, aber für Bau -, Tupel zerstört-Liste:
Also, wenn die Geschwindigkeit der iteration, oder die Indizierung sind die einzigen Faktoren, es gibt effektiv keinen Unterschied, aber für die Bau -, Tupel gewinnen.
Zusammenfassung
Tupel neigen dazu, bessere Leistungen zu erbringen als Listen in fast jeder Kategorie:
1) - Tupel werden kann Konstante gefaltet.
2) Tupel können wiederverwendet werden, anstatt kopiert.
3) Tupel sind kompakt und nicht zu zuordnen.
4) Tupel direkt auf Ihre Elemente.
Tupel kann konstant gefaltet
Tupel von Konstanten kann vorausberechnete von Python ' s peephole optimizer oder AST-Optimierer. Listen, auf der anderen Seite, gebaut-von Grund auf neu:
Tupel müssen nicht kopiert werden
Läuft
tuple(some_tuple)
kehrt sofort selbst. Da Tupel sind unveränderlich, Sie müssen nicht kopiert werden:Im Gegensatz dazu
list(some_list)
erfordert, alle Daten werden kopiert, um eine neue Liste:Tupel nicht mehr reservieren,
Da ein Tupel die Größe fixiert ist, kann es gespeichert werden kompakter als die Listen, die Notwendigkeit zu über-weisen Sie machen append() Operationen effizient.
Dieser Tupel gibt einen schönen Platz Vorteil:
Hier ist der Kommentar von Objekte/listobject.c erklärt, was Listen machen:
Tupel beziehen sich direkt auf Ihre Elemente
Referenzen auf Objekte sind, fließen direkt in ein Tupel-Objekt. Im Gegensatz dazu Listen haben eine zusätzliche Schicht der Dereferenzierung zu einem externen array von Zeigern.
Dieser Tupel gibt einen kleinen speed-Vorteil für indizierte Suchvorgänge und Auspacken:
Hier ist, wie die Tupel
(10, 20)
ist gespeichert:Hier ist, wie die Liste
[10, 20]
ist gespeichert:Beachten Sie, dass das Tupel-Objekt umfasst die beiden Daten Zeiger direkt, während die Liste-Objekt hat eine zusätzliche Schicht der Dereferenzierung zu einem externen array, die die zwei Daten Pointer.
Im wesentlichen, weil Tupel der Unveränderlichkeit bedeutet, dass der interpreter verwenden können, ein schlanker, schneller Daten-Struktur, für die es, im Vergleich zu Liste.
Einem Bereich, wo eine Liste ist vor allem schneller ist der Bau von einem generator, und insbesondere, Liste Verstehens sind viel schneller als die des nächsten Tupels entspricht,
tuple()
mit einem generator-argument:Beachten Sie insbesondere, dass
tuple(generator)
scheint ein kleines bisschen schneller alslist(generator)
, aber[elem for elem in generator]
ist viel schneller als beide.Tupel identifiziert werden, die von python compiler als eine unveränderliche Konstante
also compiler erzeugt nur einen Eintrag in der hash-Tabelle und nie geändert
Listen sind mutable-Objekte.Also compiler aktualisieren Sie den Eintrag, wenn wir die Liste aktualisieren
so ist es etwas langsamer angehen zu vergleichen, um Tupel