Gibt es Leistungsunterschiede zwischen Tupeln und Listen beim Instanziieren und Abrufen von Elementen?
python
performance
list
tuples
python-internals
Schreibgeschützt
quelle
quelle
Antworten:
Das
dis
Modul zerlegt den Bytecode für eine Funktion und ist nützlich, um den Unterschied zwischen Tupeln und Listen zu erkennen.In diesem Fall können Sie sehen, dass der Zugriff auf ein Element identischen Code generiert, das Zuweisen eines Tupels jedoch viel schneller ist als das Zuweisen einer Liste.
quelle
ListLike
mit einer Klasse zu erstellen__getitem__
, die etwas schrecklich Langsames tut, und zerlegen Sie sie dannx = ListLike((1, 2, 3, 4, 5)); y = x[2]
. Der Bytecode ähnelt eher dem obigen Tupelbeispiel als dem Listenbeispiel. Glauben Sie jedoch wirklich, dass die Leistung ähnlich ist?Im Allgemeinen können Sie erwarten, dass Tupel etwas schneller sind. Sie sollten jedoch auf jeden Fall Ihren speziellen Fall testen (wenn der Unterschied die Leistung Ihres Programms beeinträchtigen könnte - denken Sie daran, dass "vorzeitige Optimierung die Wurzel allen Übels ist").
Python macht das sehr einfach: timeit ist dein Freund.
und...
In diesem Fall ist die Instanziierung für das Tupel fast eine Größenordnung schneller, aber der Elementzugriff ist für die Liste tatsächlich etwas schneller! Wenn Sie also einige Tupel erstellen und viele Male darauf zugreifen, ist es möglicherweise schneller, stattdessen Listen zu verwenden.
Wenn Sie ein Element ändern möchten , ist die Liste natürlich schneller, da Sie ein ganz neues Tupel erstellen müssen, um ein Element davon zu ändern (da Tupel unveränderlich sind).
quelle
python -m timeit "x=tuple(xrange(999999))"
vspython -m timeit "x=list(xrange(999999))"
. Wie zu erwarten ist, dauert das Materialisieren eines Tupels etwas länger als das Auflisten einer Liste.-s "SETUP_CODE"
wird vor dem eigentlichen Zeitcode ausgeführt.Zusammenfassung
Tupel schneiden in fast jeder Kategorie besser ab als Listen :
1) Tupel können konstant gefaltet werden .
2) Tupel können wiederverwendet anstatt kopiert werden.
3) Tupel sind kompakt und nicht zu viel zugeordnet.
4) Tupel verweisen direkt auf ihre Elemente.
Tupel können konstant gefaltet werden
Tupel von Konstanten können mit Pythons Gucklochoptimierer oder AST-Optimierer vorberechnet werden. Listen hingegen werden von Grund auf neu erstellt:
Tupel müssen nicht kopiert werden
Running
tuple(some_tuple)
kehrt sofort selbst zurück. Da Tupel unveränderlich sind, müssen sie nicht kopiert werden:Im Gegensatz dazu
list(some_list)
müssen alle Daten in eine neue Liste kopiert werden:Tupel werden nicht überbelegt
Da die Größe eines Tupels festgelegt ist, kann es kompakter gespeichert werden als Listen, die überbelegt werden müssen, um append () -Operationen effizient zu gestalten.
Dies gibt Tupeln einen schönen Platzvorteil:
Hier ist der Kommentar von Objects / listobject.c , der erklärt, was Listen tun:
Tupel beziehen sich direkt auf ihre Elemente
Verweise auf Objekte werden direkt in ein Tupelobjekt aufgenommen. Im Gegensatz dazu verfügen Listen über eine zusätzliche Indirektionsebene für ein externes Array von Zeigern.
Dies gibt Tupeln einen kleinen Geschwindigkeitsvorteil für indizierte Suchvorgänge und das Auspacken:
So wird das Tupel
(10, 20)
gespeichert:So wird die Liste
[10, 20]
gespeichert:Beachten Sie, dass das Tupelobjekt die beiden Datenzeiger direkt enthält, während das Listenobjekt eine zusätzliche Indirektionsebene zu einem externen Array aufweist, das die beiden Datenzeiger enthält.
quelle
Internally, tuples are stored a little more efficiently than lists, and also tuples can be accessed slightly faster.
Wie könnten Sie dann die Ergebnisse der Antwort von dF. erklären?tuple(some_tuple)
Gibt sich nur zurücksome_tuple
, wennsome_tuple
es hashbar ist - wenn sein Inhalt rekursiv unveränderlich und hashbar ist. Andernfalls wirdtuple(some_tuple)
ein neues Tupel zurückgegeben. Zum Beispiel, wennsome_tuple
veränderbare Elemente enthalten sind.Da Tupel unveränderlich sind, sind sie speichereffizienter. listet aus Effizienzgründen den Speicher insgesamt auf, um Anhänge ohne Konstante
realloc
s zu ermöglichen . Wenn Sie also eine konstante Folge von Werten in Ihrem Code durchlaufen möchten (z. B.for direction in 'up', 'right', 'down', 'left':
), werden Tupel bevorzugt, da solche Tupel in der Kompilierungszeit vorberechnet werden.Die Zugriffsgeschwindigkeiten sollten gleich sein (beide werden als zusammenhängende Arrays im Speicher gespeichert).
Aber,
alist.append(item)
ist viel zu bevorzugen ,atuple+= (item,)
wenn Sie mit veränderbaren Daten umgehen. Denken Sie daran, dass Tupel als Datensätze ohne Feldnamen behandelt werden sollen.quelle
Sie sollten das
array
Modul auch in der Standardbibliothek berücksichtigen, wenn alle Elemente in Ihrer Liste oder Ihrem Tupel vom gleichen C-Typ sind. Es benötigt weniger Speicher und kann schneller sein.quelle
Hier ist ein weiterer kleiner Maßstab, nur um es zu tun.
Lassen Sie uns diese herausrechnen:
Man kann es fast nicht schlüssig nennen.
Aber sicher, Tupel haben sich im Vergleich zu Listen
101.239%
die Zeit oder1.239%
zusätzliche Zeit genommen, um die Arbeit zu erledigen.quelle
Tupel sollten etwas effizienter und deshalb schneller sein als Listen, weil sie unveränderlich sind.
quelle
Der Hauptgrund dafür, dass Tuple sehr effizient liest, ist, dass es unveränderlich ist.
Warum sind unveränderliche Objekte leicht zu lesen?
Der Grund dafür ist, dass Tupel im Gegensatz zu Listen im Speichercache gespeichert werden können. Das Programm liest immer aus dem Speicherort der Liste, da es veränderbar ist (kann sich jederzeit ändern).
quelle