Initialiseren van een lijst naar een bekend aantal elementen in Python

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,)*1000term 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. [[]] * 1000werkt 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 listeerst 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 putElementkan 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 Nonekan 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

Other episodes