Как работает функция filter() в Python 3

Встроенная в Python функция filter() позволяет создавать из существующего итерируемого объекта (например, из списка или словаря) новый итерируемый объект, элементы которого будут отфильтрованы согласно функции, которую мы предоставим. Итерируемый объект – это объект Python, элементы которого можно перебирать, то есть он будет возвращать элементы в последовательности (следовательно, его можно использовать в цикле for).

Читайте также:

Базовый синтаксис функции filter() таков:

filter(function, iterable)

Это вернет итерируемый объект фильтра. Чтобы составить список всех элементов, возвращаемых в объекте фильтра, можно использовать ​​функцию list().

Часто способ фильтрации значений, который предоставляет функция filter(), оказывается более эффективным, чем генераторы списков, особенно при работе с большими наборами данных. Например, генератор списка создает новый список, что, в свою очередь, увеличит время выполнения обработки. Также из этого следует, что после того, как генератор завершит работу, у нас в памяти будет два списка. А функция filter() создаст простой объект со ссылкой на исходный список, предоставленной функцией и указателем по исходному списку, что займет меньше памяти.

Читайте также: Генераторы списков в Python 3

В этом руководстве мы рассмотрим четыре различных способа использования функции filter(): с двумя разными итерационными структурами, с лямбда-функцией и без определенной функции.

Как работает filter() с функцией

Первый аргумент filter() – это функция, которая позволит нам включить или отфильтровать те или иные элементы. Функция вызывается один раз для каждого элемента в итерируемом объекте, который передается в качестве второго аргумента. Каждый раз, когда функция возвращает False, значение сбрасывается. В качестве первого аргумента можно либо передать обычную функцию, либо использовать лямбда-функцию (особенно если выражение менее сложное).

Ниже приведен синтаксис лямбды с filter():

filter(lambda item: item[] expression, iterable)

Допустим, у нас есть приведенный ниже список – это список имен рыбок, которые живут в нашем аквариуме. Тогда мы можем включить лямбда-функцию с выражением, по которому мы хотим оценивать каждый элемент из этого списка:

creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']

Чтобы отфильтровать этот список и отобрать только имена, которые начинаются с гласной, мы можем запустить следующую лямбда-функцию:

print(list(filter(lambda x: x[0].lower() in 'aeiou', creature_names)))

Здесь мы объявили элемент в списке как x. Далее мы открываем выражению доступ к первому символу каждой строки (или к нулевому символу), поэтому мы получаем x [0]. Устанавливая нижний регистр для каждого имени, мы можем быть уверены, что буквы будут соответствовать выражению ‘aeiou’.

Затем мы передаем итерируемый объект creature_names. Как и в предыдущем примере, мы применяем к результату функцию list(), чтобы создать список из итератора, возвращаемого функцией filter().

В итоге мы получим:

['Ashley', 'Olly']

Того же результата можно достичь с помощью функции, которую мы определяем:

creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie'] def names_vowels(x):
return x[0].lower() in 'aeiou'
filtered_names = filter(names_vowels, creature_names)
print(list(filtered_names))

Функция names_vowels определяет выражение, с помощью которого можно отфильтровать creature_names.

Мы получим такой же результат:

['Ashley', 'Olly']

В целом лямбда-функции в сочетании с функцией filter() дают такой же результат, что и обычная функция. Чем сложнее выражение для фильтрации данных, тем лучше использовать при этом обычную функцию – это, вероятно, будет способствовать читаемости кода.

Как filter() работает с None

Если передать функции filter() None в качестве первого аргумента, то возвращаемый итератор отфильтрует любое значение, которое Python посчитает «примерно ложным», falsy. Как правило, Python считает falsy все значения, что имеют длину 0 (как, например, пустой список или строку) или численно равно 0.

В следующем примере мы попробуем отфильтровать список, чтобы в нем отображались только номера резервуаров в нашем воображаемом аквариуме:

aquarium_tanks = [11, False, 18, 21, "", 12, 34, 0, [], {}]

В этом коде мы видим список, содержащий целые числа, пустые последовательности и логическое значение.

Давайте используем функцию filter() с параметром None и передадим список aquarium_tanks в качестве итерируемого объекта.

filtered_tanks = filter(None, aquarium_tanks)

Поскольку в качестве первого аргумента мы передали None, функция проверит, есть ли в нашем списке элементы, которые считаются ложными.

print(list(filtered_tanks))

Затем мы поместим filter_tanks в функцию list(), чтобы вывести список filter_tanks на экран.

В итоге наш вывод содержит только целые числа. Все элементы, которые оцениваются как False (а значит, эквивалентны 0 по длине), были удалены функцией filter():

[11, 25, 18, 21, 12, 34]

Примечание: Если мы не используем list() и выведем filter_tanks на экран, мы получим примерно такой объект:

<filter object at 0x7fafd5903240>

Объект фильтра является итерируемым, поэтому мы можем перебрать его с помощью цикла for или использовать list(), чтобы превратить его в список (что мы и сделали в примере выше, потому что это удобный способ просмотреть результаты).

None в функции filter() позволяет быстро удалить из списка элементы, которые считаются «примерно ложными».

Использование filter() со списком словарей

Функцию filter() можно использовать и в более сложной структуре данных. Предположим, у нас есть список словарей, где мы хотим перебрать не только каждый элемент, но и каждую пару «ключ:значение».

Для примера давайте представим, что у нас есть список всех живых существ в аквариуме, а также дополнительные сведения о каждом из них:

aquarium_creatures = [
{"name": "sammy", "species": "shark", "tank number": "11", "type": "fish"},
{"name": "ashley", "species": "crab", "tank number": "25", "type": "shellfish"},
{"name": "jo", "species": "guppy", "tank number": "18", "type": "fish"},
{"name": "jackie", "species": "lobster", "tank number": "21", "type": "shellfish"},
{"name": "charlie", "species": "clownfish", "tank number": "12", "type": "fish"},
{"name": "olly", "species": "green turtle", "tank number": "34", "type": "turtle"}
]

Далее мы попробуем отфильтровать эти данные по строке поиска, которую мы передадим функции. Чтобы функция filter() имела доступ к каждому словарю и каждому элементу в этих словаях, мы создадим вложенную функцию:

def filter_set(aquarium_creatures, search_string):
def iterator_func(x):
for v in x.values():
if search_string in v:
return True
return False
return filter(iterator_func, aquarium_creatures)

Здесь мы определили функцию filter_set(), которая принимает в качестве параметров aquarium_creatures и search_string. В filter_se () мы передаем iterator_func() как функцию filter(). Функция filter_set() вернет итератор, полученный из функции filter().

Функция iterator_func() принимает в качестве аргумента x, который представляет элемент в списке (то есть единственный словарь).

После этого цикл for обращается к значениям в каждой паре «ключ:значение» в словарях. Потом он использует условный оператор, чтобы проверить, совпадает ли search_string с v (что представляет значение).

Как и в предыдущих примерах, если выражение оценивается как True, функция добавляет этот элемент к объекту фильтра. Этот объект вернется после выполнения функции filter_set(). Мы разместили return False вне цикла, чтобы он проверил каждый элемент в каждом словаре, а не вернул результат после проверки первого же словаря.

Мы вызываем функцию filter_set() со списком словарей и поисковой строкой, по которой мы отфильтруем значения в словарях:

filtered_records = filter_set(aquarium_creatures, "2")

После выполнения функции мы получим объект фильтра, хранящийся в переменной filter_records, который мы превращаем в список и выводим на экран:

print(list(filtered_records))

Результат этого кода выглядит следующим образом:

[{'name': 'ashley', 'species': 'crab', 'tank number': '25', 'type': 'shellfish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': '21', 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': '12', 'type': 'fish'}]

Готово! У нас получилось отфильтровать список словарей по поисковой строке 2. Как видите, три словаря, которые включали значение 2, были включены в результат. Применение вложенной функции позволило нам получить доступ к каждому элементу и сравнить их с поисковой строкой.

Заключение

В этом руководстве мы на практических примерах рассмотрели разные способы использования функции filter() в Python. Теперь вы сможете опробовать функцию filter() на своих собственных примерах; попробуйте совместить ее с другой функцией, лямбда-функцией или с None для фильтрации элементов внутри структур данных различной сложности.

В данном мануале мы сразу вывели результаты filter() в формате списка. Но вполне вероятно, что в других программах вы захотите использовать возвращенный объект filter()  для дальнейших операций над этими данными.

Tags: ,

Добавить комментарий