Что такое функциональное программирование в Python
Что проверяют
Различаете ли вы парадигму и набор приёмов. Слушают, назовёте ли вы чистоту функций и неизменяемость, а не только map и lambda, и понимаете ли, в чём Python функциональному стилю помогает, а в чём мешает.
Как отвечать
Функциональное программирование строит вычисление из функций и избегает изменения внешнего состояния. Опорных понятий четыре: функции как объекты первого класса, функции высшего порядка, чистые функции (результат зависит только от аргументов, побочных эффектов нет) и неизменяемые данные.
Python мультипарадигменный и ничего из этого не навязывает, но инструменты есть:
from functools import reduce, partial
from operator import mul
nums = [1, 2, 3, 4]
evens = [n for n in nums if n % 2 == 0] # читается лучше, чем filter с lambda
as_text = list(map(str, nums)) # map уместен с готовой функцией
product = reduce(mul, nums, 1)
double = partial(mul, 2)Что стоит проговорить отдельно. Списочные включения в Python предпочитают filter с лямбдой, это устоявшийся стиль, а reduce живёт в functools, среди встроенных его нет. Генераторы дают ленивые конвейеры без промежуточных списков. Для неизменяемости берут кортежи, frozenset и датаклассы с frozen=True. Практическая выгода чистых функций в тестах: не нужны ни заглушки, ни порядок вызовов, достаточно сравнить результат.
Где спотыкаются
Называют функциональным любой код с лямбдами. Лямбда, которая пишет в журнал или дописывает внешний список, чистой не становится, и обещанные выгоды пропадают вместе с чистотой.
Считают кортеж гарантией неизменяемости. Кортеж запрещает заменять свои элементы, но вложенный в него список меняется свободно, и структура целиком остаётся изменяемой.
Заменяют циклы рекурсией по образцу функциональных языков. В Python нет оптимизации хвостовых вызовов и есть предел глубины, поэтому рекурсивный обход длинного списка упирается в исключение там, где цикл спокойно работает.