Вы используете Python главным образом для его функциональных или объектно-ориентированных функций? [закрытый]

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

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

Заранее спасибо за Ваши мнения!

29
задан Eric 6 June 2010 в 14:09
поделиться

6 ответов

Я в основном использую Python в объектно-ориентированном и процедурном стилях. На самом деле Python не особенно хорошо подходит для функционального программирования.

Многие люди думают, что пишут функциональный код на Python, используя множество lambda, map, filter и reduce, но это слишком упрощенно. Отличительной особенностью функционального программирования является отсутствие состояния или побочных эффектов. Важными элементами функционального стиля являются чистые функции, рекурсивные алгоритмы и функции первого класса.

Вот мои мысли о функциональном программировании и Python:

  • Чистые функции - это здорово. Я делаю все возможное, чтобы мои функции на уровне модулей были чистыми.

    • Чистые функции можно тестировать. Поскольку они не зависят от внешнего состояния, их гораздо легче тестировать.
    • Чистые функции могут поддерживать другие оптимизации, такие как мемоизация и тривиальное распараллеливание.
  • Программирование на основе классов может быть чистым. Если вы хотите получить эквивалент чистых функций, используя классы 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 есть циклы for, и нет ничего плохого в их использовании.
  • Не используйте рекурсивные алгоритмы. Это одна из частей функционального программирования, которую Python просто плохо поддерживает. CPython (и, думаю, все другие Python) не поддерживает оптимизацию хвостовых вызовов. Вместо этого используйте итерацию.

  • Используйте лямбду только при определении функций на лету. Анонимные функции не лучше именованных функций, последние часто более надежны, удобны в сопровождении и документированы.

53
ответ дан 28 November 2019 в 00:44
поделиться

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

Также я не думаю, что map() или filter() обычно одобряются. Напротив, обычно предпочтение отдается списковым пониманиям.

6
ответ дан 28 November 2019 в 00:44
поделиться

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

Если мне действительно нужно функциональное программирование, я использую Lisp.

1
ответ дан 28 November 2019 в 00:44
поделиться

Большинство ответов на StackOverflow - это короткие и лаконичные ответы, а функциональные аспекты python упрощают написание таких ответов.

Объектно-ориентированные функции Python просто не нужны в ответах из 10-20 строк, поэтому вы не часто видите их здесь.

5
ответ дан 28 November 2019 в 00:44
поделиться

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

23
ответ дан 28 November 2019 в 00:44
поделиться

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

Итак, в принципе, декомпозиция приложения на классы очень полезна при проектировании системы. Когда вы делаете фактическую реализацию, FP помогает написать правильный код.

Также я считаю очень обидным, что вы подразумеваете, что функциональное программирование означает просто "использовать складки везде". Это, вероятно, самое большое и самое худшее заблуждение о FP. На эту тему уже много написано, поэтому я просто скажу, что самое замечательное в FP - это идея объединять простые (,правильные и многократно используемые) функции в новые, все более и более сложные функции. Таким образом, довольно трудно написать "почти правильный" код - либо он делает именно то, что вы хотите, либо полностью ломается.

FP в Python в основном вращается вокруг написания генераторов и их родственников (list comprehensions) и вещей из модуля itertools. Явные вызовы map/filter/reduce просто не нужны.

8
ответ дан 28 November 2019 в 00:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: