Функциональное программирование
lambda, ФВП, map(), reduce(), filter(), zip(), enumerate()
Введение
Функциональное программирование — это такая методика написания программ, когда в центре внимания находятся функции. Функции могут присваиваться переменным, они могут передаваться в другие функции и порождать новые функции. Это можно назвать стилем или парадигмой программирования
В этой парадигме широко используются функции высшего порядка и анонимные функции
Функции высшего порядка (ФВП) — это функции, которые принимают в качестве аргумента другие функции и/или возвращают функции в качестве результата. Мы коснулись их в прошлом уроке, а в этой главе познакомимся поближе
Анонимные функции (lambda-функции) — безымянные функции
Анонимные функции (lambda)
Вспомним:
Функции — это небольшие подпрограммы внутри основного кода. При запуске они могут взять какие-то стартовые параметры, обработать их, получить свой результат и отдать этот результат в основной код
Чтобы вызвать функцию, нужно указать её имя, но бывают такие функции, у которых нет имени, но их всё равно можно вызывать
Пример обычной функции:
def add_func(x, y):
result = x + y
return result
print(add_func(2,3))У функции есть имя, тело функции и есть результат, который она возвращает. Чтобы вызвать эту функцию, мы указываем имя и аргументы, которые нужно обработать.
Мы можем значительно усложнить функцию, для этого добавить в неё нужные инструкции
Лямбда-функции выглядят по-другому — они не имеют имени, но у них есть ключевое слово 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