Nu gebruik ik een lijst en verwachtte iets als:
verts = list (1000)
Moet ik in plaats daarvan array gebruiken?
Antwoord 1, Autoriteit 100%
Het eerste dat voor mij opkomt is:
verts = [None]*1000
Maar heb je echt nodig om het te pretinaliseren?
Antwoord 2, Autoriteit 21%
Niet helemaal zeker waarom iedereen je moeilijk geeft om dit te willen doen – er zijn verschillende scenario’s waar je een geïnitialiseerde lijst met vaste maat wilt. En je hebt correct afgeleid dat arrays in deze gevallen verstandig zijn.
import array
verts=array.array('i',(0,)*1000)
Voor de niet-pythonistas, de (0,)*1000
term creëert een tuple met 1000 nullen. De Comma Forces Python herkent (0)
als een tuple, anders zou het worden geëvalueerd als 0.
Ik heb een tuple gebruikt in plaats van een lijst omdat ze over het algemeen lager overhead hebben.
Antwoord 3, Autoriteit 17%
Een voor de hand liggende en waarschijnlijk niet efficiënte manier is
verts = [0 for x in range(1000)]
Merk op dat dit gemakkelijk kan worden uitgebreid tot 2-dimensie.
Om bijvoorbeeld een 10×100 “array” te krijgen die u kunt doen
verts = [[0 for x in range(100)] for y in range(10)]
Antwoord 4, Autoriteit 9%
Een array met een vaste grootte willen initialiseren is in elke programmeertaal volkomen acceptabel; het is niet zo dat de programmeur een break-statement in een while(true)-lus wil plaatsen. Geloof me, vooral als de elementen gewoon worden overschreven en niet alleen worden toegevoegd/afgetrokken, zoals het geval is bij veel dynamische programmeeralgoritmen, wil je niet rommelen met append-statements en controleren of het element niet is nog on-the-fly geïnitialiseerd (dat zijn een heleboel code gents).
object = [0 for x in range(1000)]
Dit werkt voor wat de programmeur probeert te bereiken.
Antwoord 5, autoriteit 7%
@Steve gaf al een goed antwoord op je vraag:
verts = [None] * 1000
Waarschuwing:Zoals @Joachim Wuttke opmerkte, moet de lijst worden geïnitialiseerd met een onveranderlijk element. [[]] * 1000
werkt niet zoals verwacht omdat je een lijst met 1000 identieke lijsten krijgt (vergelijkbaar met een lijst van 1000 punten voor dezelfde lijst in C). Onveranderlijke objecten zoals int, str of tuple doen het prima.
Alternatieven
Het formaat van lijsten is traag. De volgende resultaten zijn niet erg verrassend:
>>> 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
Maar het formaat wijzigen is niet erg traag als je niet erg grote lijsten hebt. In plaats van de lijst te initialiseren met een enkel element (bijv. None
) en een vaste lengte om het formaat van de lijst te vermijden, zou u moeten overwegen om lijstbegrippen te gebruiken en de lijst direct te vullen met de juiste waarden. Bijvoorbeeld:
>>> %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
Vergelijking met numpy
Voor enorme datasets zijn numpy of andere geoptimaliseerde bibliotheken veel sneller:
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
Antwoord 6
Je zou dit kunnen doen:
verts = list(xrange(1000))
Dat geeft je een lijst van 1000 elementen in grootte en die toevallig wordt geïnitialiseerd met waarden van 0-999. Aangezien list
eerst een __len__
doet om de nieuwe lijst op maat te maken, zou dit redelijk efficiënt moeten zijn.
Antwoord 7
U kunt overwegen een dict
-type te gebruiken in plaats van een vooraf geïnitialiseerde lijst. De kosten van het opzoeken van een woordenboek zijn klein en vergelijkbaar met de kosten van toegang tot een willekeurig lijstelement.
En als je een mapping gebruikt, kun je schrijven:
aDict = {}
aDict[100] = fetchElement()
putElement(fetchElement(), fetchPosition(), aDict)
En de functie putElement
kan een item op elke willekeurige positie opslaan. En als je moet controleren of je verzameling een element in een bepaalde index bevat, is het meer Pythonisch om te schrijven:
if anIndex in aDict:
print "cool!"
Dan:
if not myList[anIndex] is None:
print "cool!"
Aangezien de laatste ervan uitgaat dat geen enkel echtelement in je verzameling None
kan zijn. En als dat gebeurt, gedraagt je code zich niet goed.
En als je prestatie hard nodig hebt en daarom je variabelen vooraf probeert te initialiseren en de snelst mogelijke code schrijft, verander dan je taal. De snelste code kan niet in Python worden geschreven. Probeer in plaats daarvan C en implementeer wrappers om uw vooraf geïnitialiseerde en vooraf gecompileerde code vanuit Python aan te roepen.
Antwoord 8
Als u niet meer weet over het probleemdomein, is het moeilijk om uw vraag te beantwoorden.
Tenzij u zeker weet dat u iets meer moet doen, is de pythonische manier om een lijst te initialiseren:
verts = []
Ziet u daadwerkelijk een prestatieprobleem? Zo ja, wat is de performance bottleneck?
Probeer geen probleem op te lossen dat u niet heeft. Het is waarschijnlijk dat de prestatiekosten om een array dynamisch te vullen tot 1000 elementen volkomen irrelevantzijn voor het programma dat u echt probeert te schrijven.
De klasse array is handig als de dingen in je lijst altijd een specifiek primitief type met vaste lengte zullen zijn (bijv. char, int, float). Maar het vereist ook geen pre-initialisatie.
Antwoord 9
Dit:
lst = [8 for i in range(9)]
maakt een lijst, elementen worden geïnitialiseerd 8
maar dit:
lst = [0] * 7
zou 7 lijsten maken met één element