问题:为什么Python对于函数式编程不是很好?[关闭]

我一直认为函数式编程可以在Python中完成。因此,令我感到惊讶的是,Python在这个问题上没有得到太多提及,而当提及它时,通常不是很积极。但是,没有给出太多的原因(缺少模式匹配和代数数据类型)。所以我的问题是:为什么Python对于函数式编程不是很好?除了缺乏模式匹配和代数数据类型之外,还有其他原因吗?还是这些概念对函数式编程如此重要,以致于不支持它们的语言只能被归类为一流的函数式编程语言?(请记住,我在函数式编程方面的经验非常有限。)

I have always thought that functional programming can be done in Python. Thus, I was surprised that Python didn’t get much of a mention in this question, and when it was mentioned, it normally wasn’t very positive. However, not many reasons were given for this (lack of pattern matching and algebraic data types were mentioned). So my question is: why isn’t Python very good for functional programming? Are there more reasons than its lack of pattern matching and algebraic data types? Or are these concepts so important to functional programming that a language that doesn’t support them can only be classed as a second rate functional programming language? (Keep in mind that my experience with functional programming is quite limited.)


回答 0

您所参考的问题将询问哪些语言同时促进OO和功能编程。即使Python 运作良好,它也不会促进函数式编程。

反对 Python 中的函数式编程的最佳论据是Guido仔细考虑了命令式/ OO用例,而函数式编程用例则没有。当我编写命令式Python时,它是我所知道的最漂亮的语言之一。当我编写函数式Python时,它变得和没有BDFL的普通语言一样丑陋和令人不快。

这并不是说这很糟糕,只是您必须比您改用促进功能编程的语言或改用编写OO Python的语言更加努力。

以下是我在Python中缺少的功能:


  • 没有模式匹配,也没有尾递归,这意味着必须强制性地编写基本算法。递归在Python中很丑陋而且很慢。
  • 一个小的列表库,没有功能词典,这意味着您必须自己编写很多东西。
  • 没有用于currying或composition的语法,这意味着无点样式几乎像显式传递参数一样充满标点符号。
  • 迭代器而不是惰性列表意味着您必须知道是要效率还是持久性,并且list如果需要持久性,则需要分散调用。(迭代器只能使用一次)
  • Python的简单命令式语法及其简单的LL1解析器意味着,基本上不可能为if-expressions和lambda-expressions提供更好的语法。Guido喜欢这种方式,我认为他是对的。

The question you reference asks which languages promote both OO and functional programming. Python does not promote functional programming even though it works fairly well.

The best argument against functional programming in Python is that imperative/OO use cases are carefully considered by Guido, while functional programming use cases are not. When I write imperative Python, it’s one of the prettiest languages I know. When I write functional Python, it becomes as ugly and unpleasant as your average language that doesn’t have a BDFL.

Which is not to say that it’s bad, just that you have to work harder than you would if you switched to a language that promotes functional programming or switched to writing OO Python.

Here are the functional things I miss in Python:


  • No pattern matching and no tail recursion mean your basic algorithms have to be written imperatively. Recursion is ugly and slow in Python.
  • A small list library and no functional dictionaries mean that you have to write a lot of stuff yourself.
  • No syntax for currying or composition means that point-free style is about as full of punctuation as explicitly passing arguments.
  • Iterators instead of lazy lists means that you have to know whether you want efficiency or persistence, and to scatter calls to list around if you want persistence. (Iterators are use-once)
  • Python’s simple imperative syntax, along with its simple LL1 parser, mean that a better syntax for if-expressions and lambda-expressions is basically impossible. Guido likes it this way, and I think he’s right.

回答 1

Guido 在这里对此有很好的解释。这是最相关的部分:

我从来没有考虑过Python受功能语言的严重影响,无论人们怎么说。我对诸如C和Algol 68之类的命令式语言更加熟悉,尽管我使函数成为一流的对象,但我并不认为Python是一种函数式编程语言。但是,很早以前,很明显,用户希望对列表和函数做更多的事情。

还值得注意的是,即使我没有将Python设想为一种功能语言,闭包的引入对于许多其他高级编程功能的开发也很有用。例如,新型类,装饰器和其他现代功能的某些方面都依赖此功能。

最后,尽管这些年来已经引入了许多功能编程功能,但是Python仍然缺少“真实”功能编程语言中的某些功能。例如,Python不执行某些类型的优化(例如,尾部递归)。通常,由于Python具有极强的动态特性,因此无法进行从Haskell或ML之类的功能语言中已知的那种编译时优化。很好。

我从中得出两点:

  1. 该语言的创建者并没有真正将Python视为一种功能语言。因此,有可能看到“功能式”功能,但是您不太可能看到任何确定的功能。
  2. Python的动态特性抑制了您在其他功能语言中看到的某些优化。诚然,Lisp与Python一样动态(如果不是更动态的话),因此这只是部分解释。

Guido has a good explanation of this here. Here’s the most relevant part:

I have never considered Python to be heavily influenced by functional languages, no matter what people say or think. I was much more familiar with imperative languages such as C and Algol 68 and although I had made functions first-class objects, I didn’t view Python as a functional programming language. However, earlier on, it was clear that users wanted to do much more with lists and functions.

It is also worth noting that even though I didn’t envision Python as a functional language, the introduction of closures has been useful in the development of many other advanced programming features. For example, certain aspects of new-style classes, decorators, and other modern features rely upon this capability.

Lastly, even though a number of functional programming features have been introduced over the years, Python still lacks certain features found in “real” functional programming languages. For instance, Python does not perform certain kinds of optimizations (e.g., tail recursion). In general, because Python’s extremely dynamic nature, it is impossible to do the kind of compile-time optimization known from functional languages like Haskell or ML. And that’s fine.

I pull two things out of this:

  1. The language’s creator doesn’t really consider Python to be a functional language. Therefore, it’s possible to see “functional-esque” features, but you’re unlikely to see anything that is definitively functional.
  2. Python’s dynamic nature inhibits some of the optimizations you see in other functional languages. Granted, Lisp is just as dynamic (if not more dynamic) as Python, so this is only a partial explanation.

回答 2

Scheme没有代数数据类型或模式匹配,但肯定是一种功能语言。从功能编程的角度来看,有关Python的烦人的事情:

  1. 残缺的Lambdas。由于Lambda仅包含一个表达式,并且您无法在表达式上下文中轻松地进行所有操作,因此这意味着您可以“即时”定义的功能受到限制。

  2. 如果是语句,而不是表达式。这意味着,除其他事项外,您不能在其中带有If的lambda。(这在Python 2.5中由三元数修复,但看起来很丑。)

  3. 圭多威胁要删除地图,过滤器,并减少在每过一段时间

另一方面,python具有词汇闭包,Lambda和列表理解(无论Guido是否接受,这实际上都是“功能性”概念)。我在Python中进行了大量的“函数式”编程,但是我很难说它是理想的。

Scheme doesn’t have algebraic data types or pattern matching but it’s certainly a functional language. Annoying things about Python from a functional programming perspective:

  1. Crippled Lambdas. Since Lambdas can only contain an expression, and you can’t do everything as easily in an expression context, this means that the functions you can define “on the fly” are limited.

  2. Ifs are statements, not expressions. This means, among other things, you can’t have a lambda with an If inside it. (This is fixed by ternaries in Python 2.5, but it looks ugly.)

  3. Guido threatens to remove map, filter, and reduce every once in a while

On the other hand, python has lexical closures, Lambdas, and list comprehensions (which are really a “functional” concept whether or not Guido admits it). I do plenty of “functional-style” programming in Python, but I’d hardly say it’s ideal.


回答 3

我永远都不会将Python称为“功能性的”,但每当我使用Python进行编程时,代码总是以几乎纯粹的功能性结尾。

诚然,这主要是由于列表理解非常好。因此,我不一定会建议将Python作为一种功能编程语言,但我建议对使用Python的任何人进行功能编程。

I would never call Python “functional” but whenever I program in Python the code invariably ends up being almost purely functional.

Admittedly, that’s mainly due to the extremely nice list comprehension. So I wouldn’t necessarily suggest Python as a functional programming language but I would suggest functional programming for anyone using Python.


回答 4

让我用从SO上的“功能性” Python问题的答案中摘录的一段代码来演示

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的标准库中有函数式编程有用的功能:在这种情况下iterateconcat(!!)

Let me demonstrate with a piece of code taken from an answer to a “functional” Python question on 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

The main difference here is that Haskell’s standard library has useful functions for functional programming: in this case iterate, concat, and (!!)


回答 5

对于这个问题(和答案)而言,真正重要的一件事是:函数式编程到底是什么,它的最重要特性是什么。我将尽我的看法:

函数式编程很像在白板上写数学。在白板上写方程式时,您无需考虑执行顺序。(通常)没有突变。您不会在第二天回来查看它,并且当您再次进行计算时,您会得到不同的结果(或者,如果您喝了一些新鲜的咖啡,则可以:)。基本上,板子上有什么,当您开始写下内容时,答案已经在那里,您只是还没有意识到它到底是什么。

函数式编程非常像这样。您不会改变任何事情,只需评估方程式(在本例中为“程序”),然后找出答案是什么。该程序仍然存在,未经修改。与数据相同。

我将以下内容列为函数式编程的最重要特征:a)引用透明性-如果您在其他时间和地点评估相同的语句,但具有相同的变量值,则其含义仍相同。b)没有副作用-不管您凝视白板多长时间,另一个人看着另一个白板的方程式都不会意外改变。c)函数也是值。可以传递给其他变量或与其他变量一起应用。d)函数组合,您可以执行h = g·f,从而定义一个新函数h(..),该函数等效于调用g(f(..))。

此列表按我的优先顺序排列,因此参照透明性是最重要的,其次没有副作用。

现在,如果您通过python检查语言和库在这些方面的支持和保证程度,那么您就可以很好地回答自己的问题了。

One thing that is really important for this question (and the answers) is the following: What the hell is functional programming, and what are the most important properties of it. I’ll try to give my view of it:

Functional programming is a lot like writing math on a whiteboard. When you write equations on a whiteboard, you do not think about an execution order. There is (typically) no mutation. You don’t come back the day after and look at it, and when you make the calculations again, you get a different result (or you may, if you’ve had some fresh coffee :)). Basically, what is on the board is there, and the answer was already there when you started writing things down, you just haven’t realized what it is yet.

Functional programming is a lot like that; you don’t change things, you just evaluate the equation (or in this case, “program”) and figure out what the answer is. The program is still there, unmodified. The same with the data.

I would rank the following as the most important features of functional programming: a) referential transparency – if you evaluate the same statement at some other time and place, but with the same variable values, it will still mean the same. b) no side effect – no matter how long you stare at the whiteboard, the equation another guy is looking at at another whiteboard won’t accidentally change. c) functions are values too. which can be passed around and applied with, or to, other variables. d) function composition, you can do h=g·f and thus define a new function h(..) which is equivalent to calling g(f(..)).

This list is in my prioritized order, so referential transparency is the most important, followed by no side effects.

Now, if you go through python and check how well the language and libraries supports, and guarantees, these aspects – then you are well on the way to answer your own question.


回答 6

Python几乎是一种功能语言。这是“功能精简版”。

它具有额外的功能,因此对于某些人来说还不够纯粹。

它还缺少一些功能,因此对于某些功能来说还不够完善。

缺少的功能相对容易编写。在Python中的FP上查看此类帖子。

Python is almost a functional language. It’s “functional lite”.

It has extra features, so it isn’t pure enough for some.

It also lacks some features, so it isn’t complete enough for some.

The missing features are relatively easy to write. Check out posts like this on FP in Python.


回答 7

上面未提及的另一个原因是,许多内置类型的内置函数和方法会修改对象,但不会返回修改后的对象。如果返回那些修改后的对象,那将使功能代码更简洁。例如,如果some_list.append(some_object)返回添加了some_object的some_list。

Another reason not mentioned above is that many built-in functions and methods of built-in types modify an object but do not return the modified object. If those modified objects were returned, that would make functional code cleaner and more concise. For example, if some_list.append(some_object) returned some_list with some_object appended.


回答 8

除了其他答案外,Python和大多数其他多范式语言不太适合真正的函数式编程的一个原因是,因为它们的编译器/虚拟机/运行时不支持函数优化。通过编译器理解数学规则可以实现这种优化。例如,许多编程语言都支持map函数或方法。这是一个相当标准的函数,该函数将一个函数作为一个参数,将一个Iterable作为第二个参数,然后将该函数应用于Iterable中的每个元素。

无论如何,结果map( foo() , x ) * map( foo(), y )与相同map( foo(), x * y )。后者的情况实际上比前者快,因为前者执行两份副本,后者执行一份。

更好的功能语言会识别这些基于数学的关系并自动执行优化。非专用于功能范例的语言可能不会进行优化。

In addition to other answers, one reason Python and most other multi-paradigm languages are not well suited for true functional programming is because their compilers / virtual machines / run-times do not support functional optimization. This sort of optimization is achieved by the compiler understanding mathematical rules. For example, many programming languages support a map function or method. This is a fairly standard function that takes a function as one argument and a iterable as the second argument then applies that function to each element in the iterable.

Anyways it turns out that map( foo() , x ) * map( foo(), y ) is the same as map( foo(), x * y ). The latter case is actually faster than the former because the former performs two copies where the latter performs one.

Better functional languages recognize these mathematically based relationships and automatically perform the optimization. Languages that aren’t dedicated to the functional paradigm will likely not optimize.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。