Python-Effizienz: Listen vs. Tupel

8

Ich habe eine mittlere Anzahl von Stammobjekten.

Diese Basisobjekte werden in Sammlungen eingefügt, und diese Sammlungen werden umsortiert: sortiert, gekürzt usw.

Leider ist das n groß genug, dass der Speicherverbrauch etwas beunruhigend ist und die Geschwindigkeit beunruhigend wird.

Mein Verständnis ist, dass Tupel etwas speichereffizienter sind, da sie dedupliziert sind.

Wie auch immer, ich würde gerne wissen, was die CPU / Speicher-Kompromisse von Listen gegen Tupel in Python 2.6 / 2.7 sind.

    
Paul Nathan 19.05.2011, 18:52
quelle

7 Antworten

16

Wenn Sie ein Tupel und eine Liste mit denselben Elementen haben, benötigt das Tupel weniger Platz. Da Tupel unveränderlich sind, können Sie sie nicht sortieren, hinzufügen usw. Ich empfehle Ihnen, Dieses Gespräch von Alex Gaynor für eine kurze Einführung in die Wahl der Datenstruktur in Python.

UPDATE: Wenn Sie noch genauer darüber nachdenken, sollten Sie sich die Optimierung der Raumnutzung Ihrer Objekte ansehen, zB über __slots__ oder mithilfe von namedtuple Instanzen als Proxys anstelle von tatsächliche Objekte. Dies würde wahrscheinlich zu viel größeren Einsparungen führen, da Sie N von ihnen haben und (vorläufig) nur ein paar Sammlungen, in denen sie erscheinen. Besonders namedtuple ist super super; Schauen Sie sich Raymond Hettinger's Rede .

    
Hank Gay 19.05.2011 18:55
quelle
9

Wie andere erwähnten, sind Tupel unveränderlich. Das Sortieren eines Tupels (z. B. sorted(mytuple) ) gibt eine Liste zurück, die Sie dann in ein Tupel zurückübertragen müssten.

Um ein Tupel zu sortieren (und ein Tupel zu behalten), müßten Sie folgendes tun:

%Vor%

Um eine Liste zu sortieren, müssen Sie Folgendes tun:

%Vor%

Da Sie nicht Casting und Re-Casting durchführen, ist letzteres in diesem Fall effizienter.

Machen Sie sich nicht daran, Tupel über Listen zu verwenden, es sei denn, Sie haben eine gute Begründung. Wenn Sie sortierte Daten benötigen, sind Tupel nicht der richtige Weg, es sei denn, sie werden auf diese Weise erstellt. Tupel zeichnen sich dadurch aus, dass die enthaltenen Daten NICHT ÄNDERN, z. B. bei Konfigurationseinstellungen, die zur Laufzeit geladen werden, oder bei Daten, die bereits verarbeitet wurden.

Wenn Sie anmerken, dass Sie ein großes Dataset verarbeiten, sollten Sie sich einen funktionalen Programmierstil mithilfe von Generatoren und Iteratoren über Listen und Tupel ansehen. Auf diese Weise pendeln Sie nicht herum und erstellen neue Container, sondern verketten Iterationsoperationen, um zum Endergebnis zu gelangen.

Weiterführende Literatur:

jathanism 19.05.2011 19:05
quelle
4

Was ist die (durchschnittliche, minimale, maximale) Anzahl von Stammobjekten in einer Sammlung?

Tupel sind "dedupliziert" und Listen nicht? Was bedeutet "dedupliziert" in diesem Zusammenhang?

Listen belegen mehr Arbeitsspeicher als Tupel, weil zusätzlicher Speicher unter der Annahme zugewiesen wird, dass eine Liste wachsen wird, und Sie wollen definitiv nicht jedes Mal, wenn Sie large_list.append () ausführen, Speicher neu zuweisen (). Auf einer 32-Bit-Maschine betragen die amortisierten Kosten eines zusätzlichen Listenelements 4 Byte für einen Zeiger, N Byte für das Element selbst und nicht mehr als 4 Byte für den zusätzlichen Speicher. N ist 16 Bytes für einen Float. Das bedeutet, dass eine Liste von Fließkommazahlen bis zu 24 Bytes pro extra Fließkomma benötigt, verglichen mit 20 Bytes für ein Tupel. Ein "Basisobjekt" mit N == 100 ergibt einen Vergleich von 108 gegenüber 104. Wenn auf ein basiertes Objekt in zwei Sammlungen Bezug genommen wird, dann 58 gegenüber 54. Wie groß ist Ihr N?

Hinweis: Belassen Sie Ihre Sammlungen als Listen. Konzentriere dich auf:

  • Stellen Sie sicher, dass Ihre Basisobjekte speichereffizient sind

  • Verwenden Sie Generatoren und itertools Goodies anstelle von temporären Listen, wo möglich

  • Wenn Sie nicht vermeiden können, temporäre Listen zu haben, stellen Sie sicher, dass sie sofort verworfen werden, sie werden nicht mehr benötigt, d. h. warten Sie nicht, bis die Erstellungsmethode zurückkehrt; Verwenden Sie explicit del so schnell wie möglich.

John Machin 27.05.2011 22:50
quelle
3

Zusätzlich zu all diesen Vorschlägen können Sie feststellen, dass numpy Ihre Anforderungen erfüllt. Wenn Ihre Objekte etwas sind, das standardmäßig nummeriert ist (Ints, native C-Typen usw.), dann wäre das ideal. Sie können auch ein numpliges Array mit benutzerdefinierten Objekten verwenden, aber das könnte mehr Arbeit wert sein als es wert ist.

    
Falmarri 27.05.2011 20:50
quelle
2

Sie können sie nicht auf die gleiche Weise verwenden. Tupel sind unveränderlich und unterstützen das Anhängen, Sortieren usw. nicht (das Aufrufen von sorted für ein Tupel ergibt eine Liste usw.). Tupel unterscheiden sich völlig von Listen, daher ist jeder Leistungsvergleich bedeutungslos.

    
Rafe Kettler 19.05.2011 18:55
quelle
1

Sie können ein unveränderliches Objekt nicht sortieren - d. h. wenn Sie ein Tupel sortieren, erstellen Sie immer ein neues.

    
ThiefMaster 19.05.2011 18:54
quelle
1

Es gibt mindestens zwei vorhandene Fragen, die Ihren ähnlich sind, dass die Antworten (oder Links darin) für Sie nützlich sein können. Zusammenfassend: Lassen Sie die Merkmale des Typs (veränderbar vs. unveränderlich, heterogen vs. homogen) und nicht die Leistung, um Ihre Entscheidung zu treffen, da die Unterschiede zwischen Leistung und Effizienz minimal sind.

Was ist der Unterschied zwischen Liste und Tupel in? Python?
Was sind Unterschiede zwischen List, Dictionary und Tuple in Python?

    
ajk 19.05.2011 19:03
quelle