it-swarm.com.de

Initialisieren einer Liste mit einer bekannten Anzahl von Elementen in Python

Im Moment benutze ich eine Liste und habe folgendes erwartet:

verts = list (1000)

Soll ich stattdessen Array verwenden?

225
Joan Venge

Das erste, was mir in den Sinn kommt, ist:

verts = [None]*1000

Aber müssen Sie es wirklich vorinitialisieren?

329
Steve Losh

Ich bin mir nicht sicher, warum Ihnen alle Schwierigkeiten bereiten - es gibt verschiedene Szenarien, in denen Sie eine initialisierte Liste mit fester Größe wünschen. Und Sie haben richtig festgestellt, dass Arrays in diesen Fällen sinnvoll sind.

import array
verts=array.array('i',(0,)*1000)

Für die Nicht-Pythonisten ist das (0,)*1000 term erstellt ein Tupel mit 1000 Nullen. Das Komma zwingt python zu erkennen (0) als Tupel, sonst würde es als 0 ausgewertet.

Ich habe ein Tupel anstelle einer Liste verwendet, weil sie im Allgemeinen einen geringeren Overhead haben.

70
FoxyLad

Ein offensichtlicher und wahrscheinlich nicht effizienter Weg ist

verts = [0 for x in range(1000)]

Beachten Sie, dass dies leicht auf 2-dimensionale erweitert werden kann. Zum Beispiel, um ein 10x100 "Array" zu erhalten, können Sie dies tun

verts = [[0 for x in range(100)] for y in range(10)]
60
e-shy

In jeder Programmiersprache ist es völlig akzeptabel, ein Array mit fester Größe zu initialisieren. Es ist nicht so, dass der Programmierer eine break-Anweisung in eine while-Schleife (true) setzen möchte. Glauben Sie mir, vor allem, wenn die Elemente nur überschrieben und nicht nur addiert/subtrahiert werden sollen, wie es bei vielen dynamischen Programmieralgorithmen der Fall ist, möchten Sie nicht mit Anweisungen zum Anhängen herumspielen und prüfen, ob das Element nicht vorhanden ist initialisiert noch on the fly (das ist eine Menge Code Herren).

object = [0 for x in range(1000)]

Dies funktioniert für das, was der Programmierer erreichen möchte.

30
Miko

@Steve hat Ihre Frage bereits gut beantwortet:

verts = [None] * 1000

Warnung: Wie @Joachim Wuttke betont hat, muss die Liste mit einem unveränderlichen Element initialisiert werden. [[]] * 1000 funktioniert nicht wie erwartet, da Sie eine Liste mit 1000 identischen Listen erhalten (ähnlich einer Liste mit 1000 Punkten für dieselbe Liste in C). Unveränderliche Objekte wie int, str oder Tuple reichen aus.

Alternativen

Das Ändern der Listengröße ist langsam. Die folgenden Ergebnisse sind nicht sehr überraschend:

>>> N = 10**6

>>> %timeit a = [None] * N
100 loops, best of 3: 7.41 ms per loop

>>> %timeit a = [None for x in xrange(N)]
10 loops, best of 3: 30 ms per loop

>>> %timeit a = [None for x in range(N)]
10 loops, best of 3: 67.7 ms per loop

>>> a = []
>>> %timeit for x in xrange(N): a.append(None)
10 loops, best of 3: 85.6 ms per loop

Die Größenänderung ist jedoch nicht sehr langsam, wenn Sie keine sehr großen Listen haben. Anstatt die Liste mit einem einzelnen Element (z. B. None) und einer festen Länge zu initialisieren, um eine Größenänderung der Liste zu vermeiden, sollten Sie Listenverständnisse verwenden und die Liste direkt mit korrekten Werten füllen. Zum Beispiel:

>>> %timeit a = [x**2 for x in xrange(N)]
10 loops, best of 3: 109 ms per loop

>>> def fill_list1():
    """Not too bad, but complicated code"""
    a = [None] * N
    for x in xrange(N):
        a[x] = x**2
>>> %timeit fill_list1()
10 loops, best of 3: 126 ms per loop

>>> def fill_list2():
    """This is slow, use only for small lists"""
    a = []
    for x in xrange(N):
        a.append(x**2)
>>> %timeit fill_list2()
10 loops, best of 3: 177 ms per loop

Vergleich zu numpy

Bei großen Datenmengen sind numpy oder andere optimierte Bibliotheken viel schneller:

from numpy import ndarray, zeros
%timeit empty((N,))
1000000 loops, best of 3: 788 ns per loop

%timeit zeros((N,))
100 loops, best of 3: 3.56 ms per loop
17
lumbric

Sie könnten dies tun:

verts = list(xrange(1000))

Das würde Ihnen eine Liste von 1000 Elementen in der Größe geben, die zufällig mit Werten von 0-999 initialisiert werden. Wie list ein __len__ Um die Größe der neuen Liste zu bestimmen, sollte sie ziemlich effizient sein.

4
John Montgomery

Diese:

 lst = [8 for i in range(9)]

erstellt eine Liste, Elemente werden initialisiert 8

aber dieses:

lst = [0] * 7

würde 7 Listen erstellen, die ein Element haben

0
Jutta

Sie sollten in Betracht ziehen, einen dict -Typ anstelle einer vorinitialisierten Liste zu verwenden. Die Kosten für eine Wörterbuchsuche sind gering und vergleichbar mit den Kosten für den Zugriff auf beliebige Listenelemente.

Und wenn Sie ein Mapping verwenden, können Sie schreiben:

aDict = {}
aDict[100] = fetchElement()
putElement(fetchElement(), fetchPosition(), aDict)

Die Funktion putElement kann Elemente an einer beliebigen Position speichern. Und wenn Sie überprüfen müssen, ob Ihre Sammlung ein Element an einem bestimmten Index enthält, ist es pythonischer zu schreiben:

if anIndex in aDict:
    print "cool!"

Als:

if not myList[anIndex] is None:
    print "cool!"

Da letzteres davon ausgeht, dass kein real Element in Ihrer Sammlung None sein kann. Und wenn das passiert, verhält sich Ihr Code falsch.

Und wenn Sie dringend Leistung benötigen und deshalb versuchen, Ihre Variablen vorab zu initialisieren und den schnellstmöglichen Code zu schreiben - ändern Sie Ihre Sprache. Der schnellste Code kann nicht in Python geschrieben werden. Sie sollten stattdessen C versuchen und Wrapper implementieren, um Ihren vorinitialisierten und vorkompilierten Code von Python aus aufzurufen.

0
Abgan