Iteración vs espacio , el uso podría ser un problema. En diferentes situaciones, la elaboración de perfiles puede mostrar que es "más rápida" y / o "menos memoria" intensiva.
# 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, ...]
El primer enfoque (como también lo sugirieron @jamylak , @Raymond Hettinger y @Dipto ) crea una lista duplicada en la memoria, lo que podría ser costoso para una lista grande con pocas None
entradas.
El segundo enfoque pasa por la lista una vez, y luego otra vez cada vez hasta que None
se alcanza a. Esto podría consumir menos memoria y la lista se hará más pequeña a medida que avanza. La disminución en el tamaño de la lista podría acelerar una gran cantidad de None
entradas en el frente, pero el peor de los casos sería si muchas None
entradas estuvieran en la parte posterior.
La paralelización y las técnicas in situ son otros enfoques, pero cada uno tiene sus propias complicaciones en Python. Conocer los datos y los casos de uso de tiempo de ejecución, así como perfilar el programa, es el punto de partida para operaciones intensivas o datos de gran tamaño.
Elegir cualquiera de los enfoques probablemente no importará en situaciones comunes. Se convierte más en una preferencia de notación. De hecho, en esas circunstancias poco comunes, numpy
o cython
puede ser una alternativa que valga la pena, en lugar de intentar gestionar las optimizaciones de Python.
filter
versión menos elegante :filter(lambda x: x is not None, L)
- Podrías deshacerte dellambda
usopartial
yoperator.is_not
creo, pero probablemente no valga la pena ya que la lista de compilación es mucho más limpia.