2012-01-24 16 views
18

Estoy tratando de familiarizarme con el módulo itertools y he encontrado una función llamada ifilter.itertools.ifilter vs. filtro vs. lista de comprensiones

Según lo que entiendo, se filtra e iterable en función de la función dada y devuelve un iterador sobre una lista que contiene los elementos del iterable en el que la función evalúa a True.

Pregunta 1: ¿mi interpretación es correcta hasta el momento?

Pregunta 2: aparte del hecho de que este devoluciones y iterador, en qué se diferencia de la incorporada en el filter función?

Pregunta 3 ¿Qué es más rápido?

Por lo que puedo decir, no lo es. ¿Me estoy perdiendo de algo? (Me encontré con la siguiente prueba)

>>> itertools.ifilter(lambda x: x%2, range(5)) 
<itertools.ifilter object at 0x7fb1a101b210> 
>>> for i in itertools.ifilter(lambda x: x%2, range(5)): print i 
... 
1 
3 
>>> filter(lambda x: x%2, range(5)) 
[1, 3] 
>>> function = lambda x: x%2 
>>> [item for item in range(5) if function(item)] 
[1,3] 
+0

Lo salida de qué esperabas? 'range (5)' te dará '[0,1,2,3,4]'. – istruble

+1

tenga en cuenta que la mayoría de los usos de filtro pueden ser reemplazados por un guardia en una expresión generador/lista: 'list (x para x en rango (5) si x% 2)' –

Respuesta

10

El siguiente ejemplo incluye un generador de números que imprime un mensaje inmediatamente antes de ceder el número, muestra hasta qué filter() primero construye la lista, a continuación, se ejecuta a través de eso y lo filtra. Mientras que itertools.ifilter filtra a medida que avanza, nunca construye una lista.Si está filtrando 500,000 cosas importantes, quiere ifilter, por lo que no está compilando una lista.

import itertools 

def number_generator(): 
    for i in range(0, 3): 
     print "yield", i 
     yield i 
    print "stopping" 

function = lambda x: x > 0 

numbers = number_generator() 
print "itertools.ifilter:" 
for n in itertools.ifilter(function, numbers): 
    print n 

print "\nfilter:" 
numbers = number_generator() 
for n in filter(function, numbers): 
    print n 

Salida:

 
itertools.ifilter: 
yield 0 
yield 1 
1 
yield 2 
2 
stopping 

filter: 
yield 0 
yield 1 
yield 2 
stopping 
1 
2 
3

ifilter devuelve un generador, no una lista.

Los generadores crean sus artículos sobre la marcha cuando es necesario, en lugar de asignar la lista completa primero. Esa es la única diferencia entre ifilter y filter

+1

Un generador es un iterador, y para ser estricto regresa un objeto itertools.ifilter. –

2

Aquí, se puede ver la diference:

filter(function, iterable): construir una lista de de aquellos elementos de iterable para los que la función devuelve true.

itertools.ifilter(predicate, iterable): Hacer una iterator que filtra los elementos de iterable devolviendo sólo aquellos para los que el predicado es verdadera.

Esto significa que para obtener artículos ifiltered '' que debe iterar con el iterador devuelto, pero 'filtro' devuelve todos los elementos de una lista con iteración fuera necesario.

17

Su comprensión es corret: la única diferencia es que ifilter un iterador, durante el uso de filter es como decir:

list(ifilter(...)) 

También puede estar interesado en lo PEP 289 dice de filtro y ifilter:

las listas por comprensión reducen en gran medida la necesidad de filter() y map(). Del mismo modo, se espera que las expresiones del generador minimicen la necesidad de itertools.ifilter() y itertools.imap(). [...]

en cuenta también que ifilter se convirtió filter en Python-3 (por lo tanto eliminado de itertools).