Wie man eine Liste mit einer bestimmten Größe in Python erstellt
- Vorbelegung von Speicherplatz für Listen
- Vorbelegung von Speicherplatz für andere sequentielle Datenstrukturen
Die Vorbelegung von Speicherplatz für Listen oder Arrays ist ein typisches Muster unter Programmierern wenn sie die Anzahl der Elemente im Voraus kennen.
Im Gegensatz zu C++ und Java müssen Sie in Python Ihren gesamten vorbelegten Speicher mit einigen Werten initialisieren.
Normalerweise verwenden Entwickler dafür falsche Werte, wie z.B. None
, ''
, False
und 0
.
Python bietet mehrere Möglichkeiten, eine Liste mit einer festen Größe zu erstellen, jede mit unterschiedliche Leistungsmerkmale.
Um die Leistungen verschiedener Ansätze zu vergleichen, verwenden wir den Python-Standard
Modul timeit
.
Es bietet einen praktischen Weg, um die Laufzeit von kleinen Teilen des Python-Codes zu messen.
Vorbelegung von Speicherplatz für Listen
Der erste und schnellste Weg, den *
-Operator zu verwenden, der eine Liste mit einer bestimmten
Anzahl von Malen.
>>> [None] * 10
[None, None, None, None, None, None, None, None, None, None]
Eine Million Iterationen (Standardwert der Iterationen in timeit
) dauern etwa
117 ms.
>>> timeit("[None] * 10")
0.11655918900214601
Ein anderer Ansatz ist die Verwendung der eingebauten Funktion range
mit einem Listenverständnis.
>>> [None for _ in range(10)]
[None, None, None, None, None, None, None, None, None, None]
Sie ist fast sechsmal langsamer und benötigt 612 ms Sekunde pro Million Iterationen.
>>> timeit("[None for _ in range(10)]")
0.6115895550028654
Der dritte Ansatz ist, eine einfache for
-Schleife zusammen mit der list.append()
zu verwenden.
>>> a = []
>>> for _ in range(10):
... a.append(None)
...
>>> a
[None, None, None, None, None, None, None, None, None, None]
Die Verwendung von Schleifen ist die langsamste Methode und benötigt 842 ms für eine Million Iterationen.
>>> timeit("for _ in range(10): a.append(None)", setup="a=[]")
0.8420009529945673
Vorbelegung von Speicherplatz für andere sequentielle Datenstrukturen
Da Sie Speicherplatz für eine sequentielle Datenstruktur vorbelegen, kann es sehr sinnvoll sein, die eingebaute Datenstruktur array
anstelle einer Liste zu verwenden.
>>> from array import array
>>> array('i',(0,)*10)
array('i', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Wie wir weiter unten sehen, ist dieser Ansatz nach [None] * 10
der zweitschnellste.
>>> timeit("array('i',(0,)*10)", setup="from array import array")
0.4557597979946877
Vergleichen wir die obigen reinen Python-Ansätze mit dem NumPy
Python-Paket für wissenschaftliches Rechnen.
>>> from numpy import empty
>>> empty(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
Der NumPy Weg benötigt 589 ms pro Million Iterationen.
>>> timeit("empty(10)", setup="from numpy import empty")
0.5890094790011062
Allerdings wird der NumPy-Weg für umfangreichere Listen viel schneller sein.
>>> timeit("[None]*10000")
16.059584009999526
>>> timeit("empty(10000)", setup="from numpy import empty")
1.1065983309963485
Die Schlussfolgerung ist, dass es am besten ist, sich bei kleinen Listen an [None] * 10
zu halten, aber wechseln
zu NumPys empty()
, wenn es sich um massivere sequentielle Daten handelt.