Iterazione vs spazio , l'utilizzo potrebbe essere un problema. In diverse situazioni la profilazione può mostrare di essere "più veloce" e / o "meno memoria".
# first
>>> L = [0, 23, 234, 89, None, 0, 35, 9, ...]
>>> [x for x in L if x is not None]
[0, 23, 234, 89, 0, 35, 9, ...]
# second
>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> for i in range(L.count(None)): L.remove(None)
[0, 23, 234, 89, 0, 35, 9, ...]
Il primo approccio (come suggerito anche da @jamylak , @Raymond Hettinger e @Dipto ) crea un elenco duplicato in memoria, che potrebbe essere costoso per un elenco di grandi dimensioni con poche Nonevoci.
Il secondo approccio passa attraverso l'elenco una volta e poi di nuovo ogni volta fino a quando Noneviene raggiunto un. Ciò potrebbe richiedere meno memoria e l'elenco diventerà più piccolo man mano che procede. La riduzione delle dimensioni dell'elenco potrebbe accelerare per molte Nonevoci nella parte anteriore, ma il caso peggiore sarebbe se molte Nonevoci fossero nella parte posteriore.
Parallelizzazione e tecniche sul posto sono altri approcci, ma ognuno ha le proprie complicazioni in Python. Conoscere i dati e i casi d'uso del runtime, nonché la profilazione del programma sono da dove iniziare per operazioni intensive o dati di grandi dimensioni.
Scegliere uno dei due approcci probabilmente non avrà importanza in situazioni comuni. Diventa più una preferenza di notazione. In effetti, in quelle circostanze insolite, numpyo cythonpotrebbero essere alternative utili invece di tentare di micromanage le ottimizzazioni di Python.
filterversione meno elegante :filter(lambda x: x is not None, L)- Potresti sbarazzartilambdadell'usopartialeoperator.is_notpenso, ma probabilmente non ne vale la pena poiché l'elenco-comp è molto più pulito.