Функциональное программирование
lambda, ФВП, map(), reduce(), filter(), zip(), enumerate()
Введение
Функциональное программирование — это такая методика написания программ, когда в центре внимания находятся функции. Функции могут присваиваться переменным, они могут передаваться в другие функции и порождать новые функции. Это можно назвать стилем или парадигмой программирования
В этой парадигме широко используются функции высшего порядка и анонимные функции
Функции высшего порядка (ФВП) — это функции, которые принимают в качестве аргумента другие функции и/или возвращают функции в качестве результата. Мы коснулись их в прошлом уроке, а в этой главе познакомимся поближе
Анонимные функции (lambda-функции) — безымянные функции
Анонимные функции (lambda)
Вспомним:
Функции — это небольшие подпрограммы внутри основного кода. При запуске они могут взять какие-то стартовые параметры, обработать их, получить свой результат и отдать этот результат в основной код
Чтобы вызвать функцию, нужно указать её имя, но бывают такие функции, у которых нет имени, но их всё равно можно вызывать
Пример обычной функции:
У функции есть имя, тело функции и есть результат, который она возвращает. Чтобы вызвать эту функцию, мы указываем имя и аргументы, которые нужно обработать.
Мы можем значительно усложнить функцию, для этого добавить в неё нужные инструкции
Лямбда-функции выглядят по-другому — они не имеют имени, но у них есть ключевое слово lambda.
lambda аргументы: выражение (значение функции)
лямбда-функция всегда возвращает значение
она должна быть записана в одну строку
внутри функций нет присваивания и сложной логики — это всегда простое выражение
Зачем нужны лямбда-функции?
Самое частое применение — в качестве аргументов в других функциях
Пример:
Пойдём дальше — мы можем вместо
filter_numbers
тоже использовать лямбда-функцию:
Технически, можно обойтись без лямбда-функций. Но иногда с ними получается удобнее
Практика:
Напишите четыре анонимные функции. Они должны:
Возводить переданное число в квадрат
Умножать два переданных числа
Возвращать бОльшее из двух переданных чисел
Возвращать первую букву переданного слова
Выведите на экран результат работы этих функций
Встроенные ФВП: map() filter() reduce()
map()
Допустим, мы хотим применить к каждому элементу списка какую-то функцию или операцию. Мы можем сделать при помощи цикла for:
Можем определить две функции, одна из которых принимает последовательность и функцию, а вторая является той функцией, которую нужно применить:
Есть третий способ — использовать встроенную функцию высшего порядка map()
Она принимает в качестве аргументов функцию и последовательность. И применяет переданную функцию к каждому элементу последовательности
Часто вместе в качестве аргументов для ФВП используют анонимные функции:
filter()
Как мы видим из сигнатуры, функция принимает функцию или None и итерируемую последовательность. Возвращает объект
filter
filter()
принимает функцию, которая возвращает булево значениеПопробуйте передать в качестве аргумента вместо функции значение None. Проанализируйте результат
reduce()
Для того, чтобы воспользоваться функцией
reduce()
нам понадобится импортировать её из модуляfunctools
Функция
reduce()
кумулятивно применяет функциюfunction
к элементам итерируемойiterable
последовательности, сводя её к единственному значениюПо сути результат работы
reduce()
это аккумулятор
Необязательный аргумент
initializer
— это значение аккумулятора по умолчанию, с которого начать работу. Если последовательность пустая, аккумулятор примет значениеinitializer
. Если последовательность непустая, тоinitializer
станет начальным значением аккумулятораПопробуйте применить аргумент
initializer
к примерам выше. Проанализируйте результат
Особенности объектов map, filter, reduce
Результат работы функций
map() filter() reduce()
это объектыmap filter reduce
соответственно. Это не готовые последовательности, а итераторы — интерфейсы для взаимодействия с последовательностями, но не сами последовательности.Мы можем использовать их как
iterable
объекты, но не можем увидеть всю последовательность.Сама последовательность скрыта и данные предоставляются "по запросу" — то есть только тогда, когда это потребуется
Это позволяет эффективнее использовать память, чем при хранении, например, списка
Если нам нужна сама последовательность, результат работы
map() filter() reduce()
нужно преобразовать в неё
Практика:
Задание с числами:
Входные данные: список чисел.
Используйте
map()
, чтобы возвести каждое число в квадрат.Затем к получившейся последовательности примените
filter()
, чтобы отфильтровать только нечётные числа.И к получившейся в результате последней операции последовательности примените
reduce()
, чтобы сложить оставшиеся числа в списке.
Задание с текстом:
Входные данные: список строк. Также как в прошлом задании, последовательно примените функции к списку строк.
Используйте
map()
, чтобы преобразовать каждую строку в верхний регистр.Используйте
filter()
, чтобы отфильтровать строки, которые содержат определенную подстрокуИспользуйте
reduce()
, чтобы объединить отфильтрованные строки в одну строку через запятую.Верните результат.
Для тестирования используйте следующие данные:
Некоторые полезные функции
zip()
Функция
zip()
— объединяет отдельные элементы нескольких последовательностей в кортежи. Возвращает объектzip
Примеры использования:
Попробуйте применить zip() к последовательностям разной длины. Проанализируйте результат
zip()
часто используется для создания словарей. В главе, посвященной словарям, мы узнаем, как это работает
enumerate()
Функция
enumerate
возвращает индекс элемента и сам элемент последовательности в качестве кортежа. Вот общий формат функцииenumerate
:
Пример использования:
enumerate()
часто используют в циклеfor
, когда нам нужен и элемент и его индекс:
Практика:
Напишите функцию, которая принимает на вход список чисел и возвращает новый список, состоящий из чисел, имеющих четный индекс. Используйте
enumerate()
Last updated