Почему Python не подходит для функционального программирования?

Я всегда думал, что функциональное программирование может быть выполнено в Python. Таким образом, я был удивлен, что Python не получил упоминания в этом вопросе, и, когда это было упомянуто, оно обычно не очень положительно. Однако для этого было дано не так много причин (упоминалось отсутствие сопоставления шаблонов и алгебраических типов данных). Поэтому мой вопрос: почему Python не очень хорош для функционального программирования? Есть ли больше причин, чем отсутствие соответствия шаблонов и типов алгебраических данных? Или эти понятия настолько важны для функционального программирования, что язык, который их не поддерживает, может быть классифицирован только как второй функциональный язык программирования? (Имейте в виду, что мой опыт работы с функциональным программированием довольно ограничен.)

Ответ 1

Вопрос, на который вы ссылаетесь, спрашивает, какие языки поддерживают как OO, так и функциональное программирование. Python не способствует функциональному программированию, хотя он работает достаточно хорошо.

Лучшим аргументом против функционального программирования на Python является то, что случаи использования по необходимости /OO тщательно рассматриваются Guido, в то время как варианты использования функционального программирования - нет. Когда я пишу императивный Python, это один из самых красивых языков, которые я знаю. Когда я пишу функциональный Python, он становится таким же уродливым и неприятным, как ваш средний язык, который не имеет BDFL.

Что нельзя сказать, что это плохо, просто вам нужно работать больше, чем если бы вы перешли на язык, который продвигает функциональное программирование или переключается на запись OO Python.

Вот функциональные вещи, которые я пропускаю в Python:


  • Отсутствие соответствия шаблону и отсутствие рекурсии хвоста означает, что ваши основные алгоритмы должны быть написаны императивно. В Python рекурсия уродлива и медленна.
  • Небольшая библиотека списков и функциональные словари означают, что вам приходится писать много вещей самостоятельно.
  • Ни один синтаксис для каррирования или композиции не означает, что стиль без надписей примерно такой же как пунктуация, как явно передающий аргументы.
  • Итераторы вместо ленивых списков означают, что вы должны знать, хотите ли вы эффективности или настойчивости, и разбрасывать вызовы на list, если вы хотите настойчивость. (Итераторы используются один раз)
  • Простой императивный синтаксис Python вместе с простым анализатором LL1 означает, что лучший синтаксис для if-выражений и лямбда-выражений в принципе невозможен. Гвидо любит это так, и я думаю, что он прав.

Ответ 2

У Guido есть хорошее объяснение этого здесь. Здесь самая важная часть:

Я никогда не считал Python сильно зависит от функциональных языки, независимо от того, что говорят люди или думать. Я был гораздо более знаком с императивными языками, такими как C и Алгол 68, и хотя я сделал функции первоклассных объектов, я не рассматривал Python как функциональный язык программирования. Однако ранее на, было ясно, что пользователи хотели делать гораздо больше со списками и функциями.

...

Также стоит отметить, что даже хотя я не предполагал, что Python функциональный язык, введение закрытия были полезны в развитие многих других продвинутых программирование. Например, некоторые аспекты классов нового стиля, декораторы и другие современные функции полагайтесь на эту возможность.

Наконец, несмотря на то, что ряд функциональные функции программирования были введены с годами, Python все еще не хватает определенных функций, обнаруженных в "реальное" функциональное программирование языки. Например, Python не выполнять определенные виды оптимизации (например, хвостовая рекурсия). В общем, потому что Python чрезвычайно динамического характера, невозможно вид оптимизации времени компиляции известный из функциональных языков, таких как Haskell или ML. И это прекрасно.

Я извлекаю две вещи из этого:

  • Создатель языка не считает Python функциональным языком. Таким образом, можно увидеть функциональные функции, но вы вряд ли увидите что-либо, что будет окончательно функционировать.
  • Динамическая природа Python запрещает некоторые оптимизации, которые вы видите на других функциональных языках. Конечно, Lisp так же динамичен (если не более динамический), как Python, так что это лишь частичное объяснение.

Ответ 3

Схема не имеет алгебраических типов данных или сопоставления с образцом, но, безусловно, является функциональным языком. Раздражающие вещи о Python с точки зрения функционального программирования:

  1. Искаженные лямбды. Поскольку лямбда-выражения могут содержать только выражение, и вы не можете делать все так просто в контексте выражения, это означает, что функции, которые вы можете определить "на лету", ограничены.

  2. Если это заявления, а не выражения. Это означает, что, между прочим, у вас не может быть лямбды с If внутри. (Это исправлено троичными в Python 2.5, но выглядит некрасиво.)

  3. Гвидо угрожает убрать карту, отфильтровать и уменьшить время от времени

С другой стороны, в python есть лексические замыкания, лямбды и списки (которые действительно являются "функциональной" концепцией, признает ли это Гвидо). Я много программирую в "функциональном стиле" на Python, но вряд ли скажу, что это идеально.

Ответ 4

Я бы никогда не назвал Python "функциональным", но всякий раз, когда я программирую на Python, код неизменно заканчивается почти чисто функциональным.

По общему признанию, это в основном из-за чрезвычайно приятного понимания списков. Поэтому я не буду предлагать Python в качестве функционального языка программирования, но я бы предложил функциональное программирование для любого, кто использует Python.

Ответ 5

Позвольте мне продемонстрировать часть кода, взятую из ответа на "функциональный" вопрос Python на SO

Python:

def grandKids(generation, kidsFunc, val):
  layer = [val]
  for i in xrange(generation):
    layer = itertools.chain.from_iterable(itertools.imap(kidsFunc, layer))
  return layer

Haskell:

grandKids generation kidsFunc val =
  iterate (concatMap kidsFunc) [val] !! generation

Основное различие заключается в том, что стандартная библиотека Haskell имеет полезные функции для функционального программирования: в этом случае iterate, concat и (!!)

Ответ 6

Одна вещь, которая действительно важна для этого вопроса (и ответов), такова: Какого черта функциональное программирование, и каковы его самые важные свойства. Я попытаюсь рассказать об этом:

Функциональное программирование очень похоже на написание математики на доске. Когда вы пишете уравнения на доске вы не думаете о порядке исполнения. Существует (как правило) отсутствие мутации. Вы не возвращаетесь на следующий день и не смотрите на него, и когда вы делаете расчеты снова, вы получаете другой результат (или можете, если у вас есть свежий кофе:)). В основном, то, что находится на доске, есть, и ответ был уже там, когда вы начали писать вещи вниз, вы просто не поняли, что это такое.

Функциональное программирование очень похоже на это; вы ничего не меняете, вы просто оцениваете (или в этом случае, "программа" ) и выяснить, что такое ответ. Программа все еще там, немодифицировано. То же самое с данными.

Я бы назвал следующие важные функции функционального программирования: a) ссылочная прозрачность - если вы оцениваете одно и то же выражение в какой-то другой момент  и место, но с одинаковыми значениями переменных, это будет все равно означать одно и то же. б) никакого побочного эффекта - независимо от того, как долго вы смотрите на доску, уравнение другое  парень смотрит на другую доску, случайно не изменится. c) функции тоже являются значениями. которые могут быть переданы и применены, или к другим  переменные. d) состав функции, вы можете сделать h = g · f и тем самым определить новую функцию h (..), которая  эквивалентно вызову g (f (..)).

Этот список находится в моем приоритетном порядке, поэтому ссылочная прозрачность является наиболее важной, а затем никаких побочных эффектов.

Теперь, если вы проходите через python и проверяете, насколько хорошо поддерживаются язык и библиотеки, и гарантирует, эти аспекты - тогда вы хорошо на пути, чтобы ответить на собственный вопрос.

Ответ 7

Python - это почти функциональный язык. Это "функциональный lite".

У него есть дополнительные функции, поэтому для некоторых он недостаточно чист.

В нем также отсутствуют некоторые функции, поэтому для некоторых он недостаточно полно.

Отсутствующие функции относительно легко писать. Отправляйте сообщения, например this в FP в Python.

Ответ 8

Другая причина, не упомянутая выше, заключается в том, что многие встроенные функции и методы встроенных типов модифицируют объект, но не возвращают измененный объект. Функциональный код будет чище и более кратким. Например, если some_list.append(some_object) вернул some_list с добавленным some_object.

Ответ 9

В дополнение к другим ответам, одна из причин того, что Python и большинство других языков с несколькими парадигмами плохо подходят для истинного функционального программирования, состоит в том, что их компиляторы/виртуальные машины/временные ряды не поддерживают функциональную оптимизацию. Такая оптимизация достигается благодаря пониманию математическими правилами компилятора. Например, многие языки программирования поддерживают функцию или метод map. Это довольно стандартная функция, которая принимает функцию как один аргумент и повторяется, поскольку второй аргумент применяет эту функцию к каждому элементу в итерабельном.

В любом случае оказывается, что map( foo() , x ) * map( foo(), y ) совпадает с map( foo(), x * y ). Последний случай на самом деле быстрее, чем первый, поскольку первый выполняет две копии, где последний выполняет один.

Более функциональные языки распознают эти математически основанные отношения и автоматически выполняют оптимизацию. Языки, которые не предназначены для функциональной парадигмы, скорее всего, не будут оптимизированы.