Python's filter(): Извлекает значения из Повторяющихся Значений
Оглавление
- Написание кода в функциональном стиле на Python
- Понимание проблемы фильтрации
- Начало работы с фильтром Python()
- Фильтрация повторяющихся объектов с помощью filter()
- Комбинирование фильтра() С Другими Функциональными Инструментами
- Фильтрация повторяющихся объектов с помощью filterfalse()
- Кодирование в стиле Python
- Заключение
Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Фильтрация повторяющихся объектов с помощью Python
В Python filter() есть встроенная функция, которая позволяет обрабатывать итерацию и извлекать те элементы, которые удовлетворяют заданному условию. Этот процесс широко известен как операция фильтрации. С помощью filter() вы можете применить функцию фильтрации к итерируемому объекту и создать новый итерируемый объект с элементами, которые удовлетворяют данному условию. В Python filter() является одним из инструментов, которые вы можете использовать для функционального программирования.
В этом руководстве вы узнаете, как:
- Используйте в своем коде Python
filter() - Извлеките необходимые значения из ваших итераций
- Комбинировать
filter()с другими функциональными инструментами - Заменить
filter()на другие Pythonic инструменты
Обладая этими знаниями, вы сможете эффективно использовать filter() в своем коде. В качестве альтернативы, у вас есть выбор: использовать списковые выражения или генераторные выражения, чтобы написать больше на языке Python и читаемый код.
Чтобы лучше понять filter(), вам было бы полезно иметь некоторые предварительные знания о итерациях, for циклах, функциях и lambda функциях.
Бесплатный бонус: 5 Размышления о мастерстве владения Python, бесплатный курс для разработчиков Python, который показывает вам план действий и мышление, с которым вы будете работать. вам нужно поднять свои навыки работы с Python на новый уровень.
Кодирование в функциональном стиле на Python
Функциональное программирование - это парадигма, которая поощряет использование функций для выполнения практически каждой задачи в программе. Чисто функциональный стиль основан на функциях, которые не изменяют свои входные аргументы и не меняют состояние программы. Они просто принимают определенный набор аргументов и возвращают один и тот же результат каждый раз. Такого рода функции известны как чистые функции.
В функциональном программировании функции часто оперируют массивами данных, преобразуют их и создают новые массивы с дополнительными функциями. В функциональном программировании существуют три основные операции:
- Сопоставление применяет функцию преобразования к итерируемому элементу и создает новый итерируемый элемент из преобразованных элементов.
- Фильтрация применяет предикатную, или логически значимую, функцию к итерируемому элементу и генерирует новый итерируемый элемент, содержащий элементы, удовлетворяющие требованиям Логическое условие.
- Сокращение применяет функцию сокращения к итерируемому элементу и возвращает одно суммарное значение.
На Python сильное влияние оказывают не функциональные языки, а императивные. Однако он предоставляет несколько функций, которые позволяют вам использовать функциональный стиль:
- Анонимные функции
- A
map()функция - A
filter()функция - A
reduce()функция
Функции в Python являются первоклассными объектами, что означает, что вы можете передавать их так же, как и с любым другим объектом. Вы также можете использовать их в качестве аргументов и возвращаемых значений других функций. Функции, которые принимают другие функции в качестве аргументов или возвращают функции (или и то, и другое), известны как функции высшего порядка, которые также являются желательной функцией в функциональном программировании.
В этом руководстве вы узнаете о filter(). Эта встроенная функция является одним из наиболее популярных функциональных инструментов Python.
Понимание проблемы фильтрации
Допустим, вам нужно обработать список из чисел и вернуть новый список, содержащий только те числа, которые больше 0. Быстрый способ решить эту проблему - использовать цикл for, подобный этому:
>>> numbers = [-2, -1, 0, 1, 2]
>>> def extract_positive(numbers):
... positive_numbers = []
... for number in numbers:
... if number > 0: # Filtering condition
... positive_numbers.append(number)
... return positive_numbers
...
>>> extract_positive(numbers)
[1, 2]
Цикл в extract_positive() выполняет итерацию по numbers и сохраняет каждое число, большее 0, в positive_numbers. Условный оператор отфильтровывает отрицательные числа и 0. Этот вид функциональности известен как фильтрация .
Операции фильтрации состоят из проверки каждого значения в итерационной переменной с помощью функции с предикатом и сохранения только тех значений, для которых функция выдает истинный результат. Операции фильтрации довольно распространены в программировании, поэтому большинство языков программирования предоставляют инструменты для их выполнения. В следующем разделе вы узнаете о способе фильтрации повторяющихся объектов в Python.
Начало работы с Python filter()
Python предоставляет удобную встроенную функцию filter(), которая абстрагирует логику, лежащую в основе операций фильтрации. Вот ее подпись:
filter(function, iterable)
Первый аргумент, function, должен быть функцией с одним аргументом. Обычно для этого аргумента используется функция-предикат (с логическим значением). Другими словами, вы предоставляете функцию, которая возвращает либо True, либо False в соответствии с определенным условием.
Эта function играет роль функции принятия решения, также известной как функция фильтрации, поскольку она предоставляет критерии для отфильтровывания нежелательных значений из входной итерационной таблицы и сохранения тех значений, которые вы хотите получить в результирующей итерационной таблице. Обратите внимание, что термин нежелательные значения относится к тем значениям, которые принимают значение false, когда filter() обрабатывает их с помощью function.
Примечание: Первым аргументом filter() является функциональный объект, что означает, что вам нужно передать функция без ее вызова с помощью пары круглых скобок.
Второй аргумент, iterable, может содержать любую итерацию Python, такую как список, кортеж или набор. Он также может содержать объекты generator и iterator. Важным моментом в отношении filter() является то, что он принимает только один iterable.
Чтобы выполнить процесс фильтрации, filter() применяет function к каждому элементу iterable в цикле. Результатом является итератор, который выдает значения iterable, для которых function возвращает истинное значение. Процесс не изменяет исходную входную итерацию.
Поскольку filter() написан на C и хорошо оптимизирован, его внутренний неявный цикл может быть более эффективным, чем обычный цикл for в отношении времени выполнения. Эта эффективность, пожалуй, является самым важным преимуществом использования функции в Python.
Вторым преимуществом использования filter() по сравнению с циклом является то, что он возвращает объект filter, который является итератором, который выдает значения по запросу, что способствует отложенной оценке стратегия. Возврат итератора делает filter() более эффективным использование памяти, чем эквивалентный цикл for.
Примечание: В Python 2.x, filter() возвращает list объектов. Это поведение изменилось в Python 3.x. Теперь функция возвращает объект filter, который является итератором, который выдает элементы по запросу. Итераторы Python, как известно, экономят память.
В вашем примере с положительными числами вы можете использовать filter() вместе с удобной функцией предикатов для извлечения нужных чисел. Чтобы закодировать предикат, вы можете использовать либо lambda, либо пользовательскую функцию:
>>> numbers = [-2, -1, 0, 1, 2]
>>> # Using a lambda function
>>> positive_numbers = filter(lambda n: n > 0, numbers)
>>> positive_numbers
<filter object at 0x7f3632683610>
>>> list(positive_numbers)
[1, 2]
>>> # Using a user-defined function
>>> def is_positive(n):
... return n > 0
...
>>> list(filter(is_positive, numbers))
[1, 2]
В первом примере вы используете функцию lambda, которая обеспечивает функциональность фильтрации. Вызов filter() применяет эту функцию lambda к каждому значению в numbers и отфильтровывает отрицательные числа и 0. Поскольку filter() возвращает итератор, вам нужно вызвать list(), чтобы использовать итератор и создать окончательный список.
Примечание: Поскольку filter() является встроенной функцией, вам не нужно импортировать что-либо, чтобы иметь возможность использовать это в своем коде.
Во втором примере вы пишете is_positive(), чтобы принять число в качестве аргумента и вернуть True, если число больше, чем 0. В противном случае он возвращает False. Вызов filter() применяет is_positive() к каждому значению в numbers, отфильтровывая отрицательные числа. Это решение намного более читабельно, чем его lambda эквивалент.
На практике filter() не ограничивается логическими функциями, такими как в приведенных выше примерах. Вы можете использовать другие типы функций, и filter() проверит их возвращаемое значение на достоверность:
>>> def identity(x):
... return x
...
>>> identity(42)
42
>>> objects = [0, 1, [], 4, 5, "", None, 8]
>>> list(filter(identity, objects))
[1, 4, 5, 8]
В этом примере функция фильтрации identity() возвращает не True или False явно, а тот же аргумент, который она принимает. Поскольку 0, [], "", и None являются ложными, filter() использует их истинное значение, чтобы отфильтровать их. Окончательный список содержит только те значения, которые являются достоверными в Python.
Примечание: Python следует набору правил для определения истинного значения объекта.
Например, следующие объекты являются ложными:
- Константы типа
NoneиFalse - Числовые типы с нулевым значением, например
0,0.0,0j,Decimal(0), иFraction(0, 1) - Пустые последовательности и коллекции, например
"",(),[],{},set(), иrange(0) - Объектов, которые реализуют
__bool__()с возвращаемым значениемFalseили__len__()с возвращаемым значением0
Любой другой объект будет считаться достоверным.
Наконец, если вы передадите None в function, то filter() использует идентификационную функцию и возвращает все элементы из iterable, которые оцениваются как True:
>>> objects = [0, 1, [], 4, 5, "", None, 8]
>>> list(filter(None, objects))
[1, 4, 5, 8]
В этом случае filter() проверяет каждый элемент во входной итерации, используя правила Python, которые вы видели ранее. Затем он выдает те элементы, которые оцениваются как True.
На данный момент вы изучили основы filter() и то, как это работает. В следующих разделах вы узнаете, как использовать filter() для обработки повторяющихся значений и удаления ненужных значений без цикла.
Фильтрация повторяющихся элементов С помощью filter()
Задача filter() состоит в том, чтобы применить функцию принятия решения к каждому значению во входных итерациях и вернуть новую итерацию с теми элементами, которые прошли тест. В следующих разделах приведены некоторые практические примеры, чтобы вы могли приступить к работе с filter().
Извлечение четных чисел
В качестве первого примера, допустим, вам нужно обработать список целых чисел и создать новый список, содержащий четные числа. Ваш первый подход к решению этой проблемы может заключаться в использовании цикла for, подобного этому:
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> def extract_even(numbers):
... even_numbers = []
... for number in numbers:
... if number % 2 == 0: # Filtering condition
... even_numbers.append(number)
... return even_numbers
...
>>> extract_even(numbers)
[10, 6, 50]
Здесь extract_even() принимает итерацию целых чисел и возвращает список, содержащий только те из них, которые являются четными. Условный оператор играет роль фильтра, который проверяет каждое число, чтобы выяснить, является ли оно четным или нет.
Когда вы сталкиваетесь с подобным кодом, вы можете преобразовать логику фильтрации в небольшую функцию-предикат и использовать ее с помощью filter(). Таким образом, вы можете выполнить те же вычисления без использования явного цикла:
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> def is_even(number):
... return number % 2 == 0 # Filtering condition
...
>>> list(filter(is_even, numbers))
[10, 6, 50]
Здесь is_even() принимает целое число и возвращает True, если оно четное, и False в противном случае. Вызов filter() выполняет сложную работу и отфильтровывает нечетные числа. В результате вы получаете список четных чисел. Этот код короче и эффективнее, чем его эквивалентный цикл for.
Поиск простых чисел
Другим интересным примером может быть извлечение всех простых чисел за заданный интервал. Чтобы сделать это, вы можете начать с кодирования функции-предиката, которая принимает целое число в качестве аргумента и возвращает True, если число простое, и False в противном случае. Вот как это можно сделать:
>>> import math
>>> def is_prime(n):
... if n <= 1:
... return False
... for i in range(2, int(math.sqrt(n)) + 1):
... if n % i == 0:
... return False
... return True
...
>>> is_prime(5)
True
>>> is_prime(12)
False
Логика фильтрации теперь находится в is_prime(). Функция выполняет итерацию по целым числам между 2 и квадратным корнем из n. Внутри цикла условный оператор проверяет, делится ли текущее число на любое другое в интервале. Если это так, то функция возвращает False, поскольку число не является простым. В противном случае он возвращает True, сигнализируя о том, что введенное число является простым.
Установив и протестировав is_prime(), вы можете использовать filter() для извлечения простых чисел из интервала, подобного этому:
>>> list(filter(is_prime, range(1, 51)))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Этот вызов filter() извлекает все простые числа в диапазоне от 1 до 50. Алгоритм, используемый в is_prime(), взят из статьи Википедии о тестах на первичность. Вы можете ознакомиться с этой статьей, если вам нужны более эффективные подходы.
Удаление выбросов в выборке
Когда вы пытаетесь описать и обобщить выборку данных, вы, вероятно, начинаете с определения ее среднего значения. Среднее значение является довольно популярным показателем центральной тенденции и часто является первым подходом к анализу набора данных. Это дает вам краткое представление о центре или местоположении данных.
В некоторых случаях среднее значение не является достаточно хорошим показателем центральной тенденции для данной выборки. Выбросы являются одним из элементов, влияющих на точность среднего значения. Выбросы - это точки данных, которые значительно отличаются от других наблюдений в выборке или генеральной совокупности. Кроме этого, в статистике для них нет однозначного математического определения.
Однако в нормально распределенных выборках выбросы часто определяются как точки данных, которые находятся более чем на два стандартных отклонения от среднего значения выборки.
Теперь предположим, что у вас есть нормально распределенная выборка с некоторыми отклонениями, которые влияют на точность среднего значения. Вы изучили отклонения и знаете, что это неверные данные. Вот как вы можете использовать несколько функций из модуля statistics вместе с filter() для очистки ваших данных:
>>> import statistics as st
>>> sample = [10, 8, 10, 8, 2, 7, 9, 3, 34, 9, 5, 9, 25]
>>> # The mean before removing outliers
>>> mean = st.mean(sample)
>>> mean
10.692307692307692
>>> stdev = st.stdev(sample)
>>> low = mean - 2 * stdev
>>> high = mean + 2 * stdev
>>> clean_sample = list(filter(lambda x: low <= x <= high, sample))
>>> clean_sample
[10, 8, 10, 8, 2, 7, 9, 3, 9, 5, 9, 25]
>>> # The mean after removing outliers
>>> st.mean(clean_sample)
8.75
В выделенной строке функция lambda возвращает True, если заданная точка данных находится между средним значением и двумя стандартными отклонениями. В противном случае она возвращает False. При фильтрации sample с помощью этой функции 34 исключается. После такой очистки среднее значение выборки будет значительно отличаться.
Проверка идентификаторов Python
Вы также можете использовать filter() с итерационными таблицами, содержащими нечисловые данные. Например, предположим, что вам нужно обработать список строк и извлечь те из них, которые являются допустимыми идентификаторами Python . Проведя некоторое исследование, вы обнаружите, что Python str предоставляет метод под названием .isidentifier(), который может помочь вам с этой проверкой.
Вот как вы можете использовать filter() вместе с str.isidentifier() для быстрой проверки идентификаторов:
>>> words = ["variable", "file#", "header", "_non_public", "123Class"]
>>> list(filter(str.isidentifier, words))
['variable', 'header', '_non_public']
В этом случае filter() запускает .isidentifier() для каждой строки в words. Если строка является допустимым идентификатором Python, то она включается в конечный результат. В противном случае слово будет отфильтровано. Обратите внимание, что вам нужно использовать str для доступа к .isidentifier() при вызове filter().
Примечание: Кроме того, .isidentifier(), str предоставляет богатый набор .is*() методов, которые могут быть полезны для фильтрации повторяющихся значений строк.
Наконец, интересным упражнением может быть продолжение примера и проверка того, является ли идентификатор также ключевым словом. Давайте, попробуйте! Подсказка: вы можете использовать .kwlist из модуля keyword.
Поиск слов-палиндромов
Упражнение, которое часто возникает при знакомстве со строками Python, состоит в том, чтобы найти слова-палиндромы в списке строк. Слово-палиндром читается как в обратном порядке, так и в прямом. Типичными примерами являются “мадам” и “гоночный автомобиль”.
Чтобы решить эту проблему, вы начнете с написания функции-предиката, которая принимает строку и проверяет, одинаково ли она читается в обоих направлениях, вперед и назад. Вот возможная реализация:
>>> def is_palindrome(word):
... reversed_word = "".join(reversed(word))
... return word.lower() == reversed_word.lower()
...
>>> is_palindrome("Racecar")
True
>>> is_palindrome("Python")
False
В is_palindrome() вы сначала изменяете исходное значение word и сохраняете его в reversed_word. Затем вы возвращаете результат сравнения обоих слов на равенство. В этом случае вы используете .lower(), чтобы избежать различий, связанных с регистром. Если вы вызываете функцию со словом-палиндромом, то получаете True. В противном случае вы получите False.
У вас уже есть рабочая функция определения предикатов для определения слов-палиндромов. Вот как вы можете использовать filter() для выполнения сложной работы:
>>> words = ("filter", "Ana", "hello", "world", "madam", "racecar")
>>> list(filter(is_palindrome, words))
['Ana', 'madam', 'racecar']
Круто! Ваша комбинация filter() и is_palindrome() работает правильно. Кроме того, она лаконична, удобочитаема и эффективна. Отличная работа!
Комбинирование filter() С другими Функциональными Инструментами
Итак, вы узнали, как использовать filter() для выполнения различных операций фильтрации для повторяющихся объектов. На практике вы можете комбинировать filter() с другими функциональными инструментами для выполнения множества различных задач с повторяемыми объектами без использования явных циклов. В следующих двух разделах вы познакомитесь с основами использования filter(), а также map() и reduce().
Квадрат четных чисел: filter() и map()
Иногда вам нужно взять итерационную таблицу, обработать каждый из ее элементов с помощью функции преобразования и создать новую итерационную таблицу с результирующими элементами. В этом случае вы можете использовать map(). Функция имеет следующую сигнатуру:
map(function, iterable[, iterable1, ..., iterableN])
Аргументы работают следующим образом:
functionсодержит функцию преобразования. Эта функция должна принимать столько аргументов, сколько итераций вы передаете вmap().iterableсодержит итерацию на Python. Обратите внимание, что вы можете указать несколько итераций вmap(), но это необязательно.
map() применяет function к каждому элементу в iterable, чтобы преобразовать его в другое значение с дополнительными функциями. Затем map() выдает каждый преобразованный элемент по запросу.
Чтобы проиллюстрировать, как вы можете использовать filter() вместе с map(), предположим, вам нужно вычислить квадратичное значение всех четных чисел в данном списке. В этом случае вы можете использовать filter() для извлечения четных чисел, а затем map() для вычисления квадратных значений:
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> def is_even(number):
... return number % 2 == 0
...
>>> even_numbers = list(filter(is_even, numbers))
>>> even_numbers
[10, 6, 50]
>>> list(map(lambda n: n ** 2, even_numbers))
[100, 36, 2500]
>>> list(map(lambda n: n ** 2, filter(is_even, numbers)))
[100, 36, 2500]
Сначала вы получаете четные числа, используя filter() и is_even() точно так же, как вы делали это до сих пор. Затем вы вызываете map() с помощью функции lambda, которая принимает число и возвращает его квадратное значение. Вызов map() применяет функцию lambda к каждому числу в even_numbers, так что вы получаете список четных квадратных чисел. В последнем примере показано, как объединить filter() и map() в одном выражении.
Сумма четных чисел: filter() и reduce()
Еще одним функциональным инструментом программирования на Python является reduce(). В отличие от filter() и map(), которые по-прежнему являются встроенными функциями, reduce() был перенесен в модуль functools. Эта функция полезна, когда вам нужно применить функцию к итерируемой переменной и свести ее к одному суммарному значению. Такого рода операции обычно известны как сокращение или сворачивание.
Подпись reduce() выглядит следующим образом:
reduce(function, iterable, initial)
Вот что означают эти аргументы:
functionсодержит любой вызываемый объект Python, который принимает два аргумента и возвращает одно значение.iterableсодержит любую итерацию на Python.initialсодержит значение, которое служит отправной точкой для первого частичного вычисления или сокращения. Это необязательный аргумент.
Вызов reduce() начинается с применения function к первым двум элементам в iterable. Таким образом, он вычисляет первый суммарный результат, называемый накопителем. Затем reduce() использует накопитель и третий элемент в iterable для вычисления следующего суммарного результата. Процесс продолжается до тех пор, пока функция не вернет одно значение.
Если вы укажете значение в initial, то reduce() выполнит первое частичное вычисление, используя initial и первый элемент из iterable.
Вот пример, который объединяет filter() и reduce() для суммарного вычисления общей суммы всех четных чисел в списке:
>>> from functools import reduce
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> def is_even(number):
... return number % 2 == 0
...
>>> even_numbers = list(filter(is_even, numbers))
>>> reduce(lambda a, b: a + b, even_numbers)
66
>>> reduce(lambda a, b: a + b, filter(is_even, numbers))
66
Здесь первый вызов reduce() вычисляет сумму всех четных чисел, которые содержит filter(). Для этого reduce() использует функцию lambda, которая складывает два числа одновременно.
В последнем примере показано, как связать filter() и reduce(), чтобы получить тот же результат, который вы получали ранее.
Фильтрация повторяющихся элементов С помощью filterfalse()
В itertools, вы найдете функцию с именем filterfalse(), которая выполняет обратное filter() действие. Он принимает iterable в качестве аргумента и возвращает новый итератор, который выдает элементы, для которых функция принятия решения возвращает ложный результат. Если вы используете None в качестве первого аргумента для filterfalse(), то вы получите ложные элементы.
Смысл использования функции filterfalse() в том, чтобы способствовать повторному использованию кода. Если у вас уже есть функция принятия решения, вы можете использовать ее с помощью filterfalse() для получения отклоненных элементов. Это избавит вас от необходимости кодировать обратную функцию принятия решения.
В следующих разделах вы закодируете несколько примеров, которые покажут, как вы можете воспользоваться преимуществами filterfalse() для повторного использования существующих функций принятия решений и продолжения выполнения некоторой фильтрации.
Извлечение нечетных чисел
Вы уже закодировали функцию-предикат с именем is_even(), чтобы проверить, является ли число четным или нет. С помощью этой функции и filterfalse() вы можете создать итератор, который выдает нечетные числа, без необходимости кодировать функцию is_odd():
>>> from itertools import filterfalse
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> def is_even(number):
... return number % 2 == 0
...
>>> list(filterfalse(is_even, numbers))
[1, 3, 45]
В этом примере filterfalse() возвращает итератор, который возвращает нечетные числа из входного итератора. Обратите внимание, что вызов filterfalse() прост и удобочитаем.
Фильтрация значений NaN
Иногда, когда вы работаете с арифметикой с плавающей запятой, вы можете столкнуться с проблемой наличия NaN (не числа) значений. Например, предположим, что вы вычисляете среднее значение выборки данных, содержащей значения NaN. Если вы используете модуль Python statistics для этого вычисления, то получите следующий результат:
>>> import statistics as st
>>> sample = [10.1, 8.3, 10.4, 8.8, float("nan"), 7.2, float("nan")]
>>> st.mean(sample)
nan
В этом примере вызов mean() возвращает nan, что является не самым информативным значением, которое вы можете получить. Значения NaN могут иметь различное происхождение. Они могут возникать из-за неверных входных данных, поврежденных данных и т.д. Вам следует найти правильную стратегию борьбы с ними в ваших приложениях. Одной из альтернатив может быть удаление их из ваших данных.
Модуль math предоставляет удобную функцию под названием isnan(), которая может помочь вам решить эту проблему. Функция принимает число x в качестве аргумента и возвращает True, если x является NaN, и False в противном случае. Вы можете использовать эту функцию для предоставления критериев фильтрации в вызове filterfalse():
>>> import math
>>> import statistics as st
>>> from itertools import filterfalse
>>> sample = [10.1, 8.3, 10.4, 8.8, float("nan"), 7.2, float("nan")]
>>> st.mean(filterfalse(math.isnan, sample))
8.96
Использование math.isnan() вместе с filterfalse() позволяет исключить все значения NaN из вычисления среднего значения. Обратите внимание, что после фильтрации вызов mean() возвращает значение, которое обеспечивает лучшее описание ваших выборочных данных.
Кодирование в стиле Python
Несмотря на то, что map(), filter(), и reduce() уже давно существуют в экосистеме Python, перечислите основные понятия и генераторные выражения стали сильными конкурентами Python практически в каждом случае использования.
Функциональность, предоставляемая этими функциями, почти всегда более явно выражена с помощью генераторного выражения или алгоритма распознавания списка. В следующих двух разделах вы узнаете, как заменить вызов filter() на алгоритм распознавания списка или генераторное выражение. Эта замена сделает ваш код более понятным на языке Python.
Заменяя filter() На Понимание списка
Вы можете использовать следующий шаблон, чтобы быстро заменить вызов filter() эквивалентным списком для понимания:
# Generating a list with filter()
list(filter(function, iterable))
# Generating a list with a list comprehension
[item for item in iterable if function(item)]
В обоих случаях конечной целью является создание объекта list. Подход к пониманию списка более понятен, чем его эквивалентная конструкция filter(). Беглое ознакомление с понятием раскрывает итерацию, а также функциональность фильтрации в предложении if.
Использование списковых вычислений вместо filter() - это, вероятно, путь, по которому в настоящее время идет большинство разработчиков Python. Однако у списковых вычислений есть некоторые недостатки по сравнению с filter(). Наиболее заметным из них является отсутствие отложенной оценки. Кроме того, когда разработчики начинают читать код, в котором используется filter(), они сразу понимают, что код выполняет операции фильтрации. Однако это не так очевидно в коде, в котором с той же целью используется понимание списков.
При преобразовании конструкции filter() в функцию понимания списка следует обратить внимание на то, что если вы передадите None в первый аргумент filter(), то эквивалентное понимание списка будет выглядеть следующим образом:
# Generating a list with filter() and None
list(filter(None, iterable))
# Equivalent list comprehension
[item for item in iterable if item]
В данном случае предложение if в списке на понимание проверяет item на его истинностное значение. Этот тест соответствует стандартным правилам Python относительно истинностных значений, которые вы уже видели.
Вот пример замены filter() на понимание списка для построения списка четных чисел:
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> # Filtering function
>>> def is_even(x):
... return x % 2 == 0
...
>>> # Use filter()
>>> list(filter(is_even, numbers))
[10, 6, 50]
>>> # Use a list comprehension
>>> [number for number in numbers if is_even(number)]
[10, 6, 50]
В этом примере вы можете видеть, что вариант понимания списка более понятен. Он читается почти как обычный английский. Решение для понимания списка также позволяет избежать необходимости вызывать list() для создания окончательного списка.
Заменяя filter() На генераторное выражение
Естественной заменой filter() является генераторное выражение. Это потому, что filter() возвращает итератор, который выдает элементы по запросу, точно так же, как это делает выражение-генератор. Известно, что итераторы Python экономят память. Вот почему filter() теперь возвращает итератор вместо списка.
Вот как вы можете использовать генераторные выражения для написания примера из приведенного выше раздела:
>>> numbers = [1, 3, 10, 45, 6, 50]
>>> # Filtering function
>>> def is_even(x):
... return x % 2 == 0
...
>>> # Use filter()
>>> even_numbers = filter(is_even, numbers)
>>> even_numbers
<filter object at 0x7f58691de4c0>
>>> list(even_numbers)
[10, 6, 50]
>>> # Use a generator expression
>>> even_numbers = (number for number in numbers if is_even(number))
>>> even_numbers
<generator object <genexpr> at 0x7f586ade04a0>
>>> list(even_numbers)
[10, 6, 50]
Генераторное выражение так же эффективно, как и вызов filter(), с точки зрения потребления памяти. Оба инструмента возвращают итераторы, которые выдают элементы по запросу. Использование любого из них может быть вопросом вкуса, удобства или стиля. Итак, ты главный!
Заключение
Функция filter() в Python позволяет выполнять операции фильтрации над повторяющимися объектами. Такого рода операция заключается в применении логической функции к элементам в iterable и сохранении только тех значений, для которых функция возвращает истинный результат. В общем, вы можете использовать filter() для обработки существующих итераций и создания новых итераций, содержащих значения, которые вам нужны в данный момент.
В этом руководстве вы узнали, как:
- Работа с Python'ами
filter() - Используйте
filter()для обработки повторяющихся значений и сохраняйте нужные значения - Комбинировать
filter()сmap()иreduce()для решения различных задач - Заменить
filter()на перечислить значения и генераторных выражений
Благодаря этим новым знаниям вы теперь можете использовать filter() в своем коде, чтобы придать ему функциональный стиль. Вы также можете переключиться на более понятный стиль Python и заменить filter() на список значений или генераторных выражений.
<статус завершения article-slug="python-filter-function" class="btn-group mb-0" data-api-article-bookmark-url="/api/v1/articles/python-filter-function/bookmark/" данные-api-статья-статус завершения-url="/api/v1/articles/python-filter-function/completion_status/"> статус завершения> <поделиться-кнопка bluesky-text="Интересная статья #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей на Python:%0A%0apython's filter(): Извлекать значения из повторяющихся значений" email-subject="Статья на Python для вас" twitter-text="Интересная статья на #Python от @realpython:" url="https://realpython.com/python-filter-function /" url-title="Фильтр Python(): извлечение значений из повторяющихся значений"> кнопка "поделиться">
Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Фильтрация повторяющихся объектов с помощью Python
Back to Top