itertools.ifilter Vs. фильтр против список пониманий - PullRequest
24 голосов
/ 25 января 2012

Я пытаюсь поближе познакомиться с модулем itertools и обнаружил функцию с именем ifilter.

. Насколько я понимаю, он фильтрует и повторяет на основе данной функции и возвращает итератор.над списком, содержащим элементы итерируемого элемента, для которого функция оценивается как True.

Вопрос 1 : правильное ли мое понимание до сих пор?

Вопрос 2 : кроме того, что это возвращает и итератор, как этоотличается от встроенной функции filter?

Вопрос 3 Что быстрее?

Из того, что я могу сказать, это не так.Я что-то пропустил?(Я провел следующий тест)

>>> 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]

Ответы [ 4 ]

19 голосов
/ 25 января 2012

Ваше понимание верно: единственное отличие состоит в том, что ifilter возвращает итератор, а использование filter похоже на вызов:

list(ifilter(...))

Вас также может интересовать, что PEP 289 говорит о фильтре и ifilter:

Понимание списка значительно уменьшило потребность в filter() и map().Аналогично, ожидается, что выражения-генераторы минимизируют потребность в itertools.ifilter() и itertools.imap().[...]

Также обратите внимание, что ifilter стал filter в Python-3 (следовательно, удален из itertools).

15 голосов
/ 31 марта 2013

Пример ниже включает генератор чисел, который печатает сообщение непосредственно перед получением номера, показывает, как filter() сначала строит список, затем просматривает его и фильтрует.Принимая во внимание, что itertools.ifilter фильтрует по ходу дела, никогда не создавая список.Если вы фильтруете 500 000 значимых вещей, вам нужно ifilter, поэтому вы не строите список.

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

Вывод:

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

filter:
yield 0
yield 1
yield 2
stopping
1
2
3 голосов
/ 25 января 2012

ifilter возвращает генератор, а не список.

Генераторы создают свои элементы на лету, когда это необходимо, вместо того, чтобы сначала распределять весь список. Это единственная разница между ifilter и filter

2 голосов
/ 25 января 2012

Здесь вы можете увидеть разницу:

filter (function, iterable) : Построить список из тех элементов итерируемых, для которых функция возвращает true.

itertools.ifilter (предикат, повторяемый) : Создайте итератор , который фильтрует элементы из повторяемого элемента, возвращая только те, для которых предикат равен True.

Это означает, что для получения «ifiltered» элементов вы должны выполнять итерацию с возвращенным итератором, но «filter» возвращает все элементы в списке без необходимости итерации.

...