Ответ 1
В основном я использую Python с использованием объектно-ориентированных и процедурных стилей. Python на самом деле не особенно хорошо подходит для функционального программирования.
Многие думают, что они пишут функциональный код Python, используя множество lambda
, map
, filter
и reduce
, но это немного упрощено. Особенностью функционального программирования является отсутствие состояния или побочных эффектов. Важными элементами функционального стиля являются чистые функции, рекурсивные алгоритмы и функции первого класса.
Вот мои мысли о функциональном программировании и Python:
-
Чистые функции велики. Я делаю все возможное, чтобы мои функции на модульном уровне были чистыми.
- Чистые функции могут быть протестированы. Поскольку они не зависят от внешнего состояния, их намного легче проверить.
- Чистые функции могут поддерживать другие оптимизации, такие как memoization и тривиальная распараллеливание.
-
Программирование на основе классов может быть чистым. Если вам нужен эквивалент чистым функциям с использованием классов Python (что иногда, но не всегда, что вы хотите),
- Сделайте ваши экземпляры неизменными. В частности, это в основном означает, что ваши методы всегда возвращают новые экземпляры вашего класса, а не меняют текущий.
- Использовать инъекцию зависимостей, а не получать материал (например, импортированный модуль) из глобальной области.
- Это не всегда может быть именно то, что вы хотите.
-
Не пытайтесь избежать состояния вместе. Это не разумная стратегия в Python. Например, используйте
some_list.append(foo)
, а неnew_list = some_list + [foo]
, первая из которых более идиоматична и эффективна. (Действительно, тонна "функциональных" решений, которые я вижу, что люди используют в Python, алгоритмически субоптимальна по сравнению с просто-простыми или более простыми решениями, которые не являются функциональными или функциональными, но не используют функционально выглядящие инструменты. ) -
Изучите лучшие уроки функционального программирования, например изменяемое состояние опасно. Задайте себе вопрос: действительно ли я хочу изменить этот X или мне нужен новый X?
-
Одно действительно обычное место, которое возникает при обработке списка. Я бы использовал
foo = [bar(item.baz()) for item in foo]
а не
for index, _ in enumerate(foo): foo[index] = bar(foo[index].baz())
и тому подобное. Это позволяет избежать путаных ошибок, когда один и тот же объект списка хранится в другом месте и не должен изменяться. (Если он должен быть изменен, тогда есть приличная вероятность, что у вас есть ошибка дизайна. Мутирование некоторых списков, на которые вы ссылались на несколько мест, не является отличным способом совместного использования состояния.)
-
-
Не используйте
map
и друзей безвозмездно. Нет ничего более функционального в этом.-
map
/filter
не более функциональные, чем списки. Список понятий был заимствован из Haskell, чистого функционального языка.map
и особенноfilter
может быть сложнее понять, чем понимание списка. Я бы никогда не использовалmap
илиfilter
с лямбдой, но мог бы, если бы у меня была уже существующая функция; Я используюmap
приличный бит. - То же самое относится к
itertools.imap
/ifilter
по сравнению с выражениями генератора. (Эти вещи несколько ленивы, что является чем-то большим, что мы можем заимствовать из функционального мира.) - Не используйте
map
иfilter
для побочных эффектов. Я вижу это сmap
много, что делает сложный код, ненужные списки и явно не работает (несмотря на то, что люди думают, что это должно быть из-заmap
.) Просто используйте цикл for. -
reduce
запутан, за исключением очень простых случаев. У Python есть петли, и нет никакого вреда в их использовании.
-
-
Не используйте рекурсивные алгоритмы. Это одна часть функционального программирования. Python просто не поддерживает. CPython (и я думаю, что все остальные Python) не поддерживают оптимизацию хвостовых вызовов. Вместо этого используйте итерацию.
-
Используйте только
lambda
, когда вы определяете функции "на лету". Анонимные функции не лучше, чем именованные функции, последние из которых часто более надежны, поддерживаются и документируются.