您是否主要使用Python来实现其功能或面向对象的功能?

时间:2010-06-06 14:09:44

标签: python oop functional-programming

我看到StackOverflow上的大多数Python开发人员认可使用简洁的功能工具,如lambdas,地图,过滤器等,而其他人则认为他们的代码更清晰,更易于维护而不使用它们。你有什么偏好?

另外,如果你是一个顽固的功能程序员或OO的硬核,你认为哪种其他特定的编程实践最适合你的风格?

提前感谢您的意见!

6 个答案:

答案 0 :(得分:48)

我主要使用Python使用面向对象和程序样式。 Python实际上并不特别适合函数式编程。

许多人认为他们使用大量lambdamapfilterreduce编写功能性Python代码,但这有点过了 - 简化。功能编程的标志性特征是缺乏状态或副作用。功能样式的重要元素是纯函数,递归算法和第一类函数。

以下是我对函数式编程和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())
      

      和类似的东西。这避免了将相同列表对象存储在别处并且不应更改的错误。 (如果 应该更改,那么你很可能会遇到设计错误。改变一些你引用多个地方的列表并不是分享状态的好方法。)

      < / LI>
  • 不要无偿地使用map和朋友。没有更多功能可以做到这一点。

    • map / filter 比列表推导功能更强大。列表推导是从纯函数语言Haskell借来的。 map,尤其是filter比列表理解更难理解。我永远不会将mapfilter与lambda一起使用,但如果我有一个已经存在的函数,我可能会这样做;我使用map一点点。
    • 与生成器表达式相比,itertools.imap / ifilter也是如此。 (这些东西有点懒,这是我们可以从功能世界中借鉴的东西。)
    • 不要将mapfilter用于副作用。我用map看了很多,这使得难以理解的代码,不需要的列表,并且显然不起作用(尽管人们认为它必须是因为map。)只需使用for循环。
    • 除了非常简单的案例外,
    • reduce令人困惑。 Python有for循环,使用它们没什么坏处。
  • 不要使用递归算法。这是函数式编程的一部分,Python不能很好地支持。 CPython(我认为所有其他Pythons)都不支持尾调用优化。 改为使用迭代。

  • 在动态定义函数时仅使用lambda匿名函数并不比命名函数更好,后者通常更健壮,可维护,并记录在案。

答案 1 :(得分:22)

我使用可以使用最短,最干净的代码完成工作的语言功能。如果这意味着我必须将两者混合,我经常这样做,那就是完成的事情。

答案 2 :(得分:8)

我既是一个顽固的OOP和功能性程序员,这些风格很好地协同工作,主要是因为它们是完全正交的。有很多面向对象的函数式语言,Python就是其中之一。

基本上,在设计系统时,将应用程序分解为类非常有用。当您进行实际实施时,FP有助于编写正确的代码。

另外我觉得非常冒犯你暗示功能性编程只是意味着“在任何地方使用折叠”。这可能是关于FP的最大和最坏的误解。关于该主题已经写了很多,所以我只想说FP的优点是将简单(,正确和可重用)函数组合成新的,越来越复杂的函数。这样,编写“几乎正确”的代码非常困难 - 要么整个事情完全符合您的要求,要么完全破坏。

Python中的FP主要围绕编写生成器及其亲属(列表推导)和itertools模块中的内容。显式地图/过滤/减少调用是不必要的。

答案 3 :(得分:6)

Python只有边缘功能编程功能,所以如果很多人特别使用它,我会感到惊讶。例如,没有标准的方法来进行函数组合,标准库的reduce()已被弃用,而不支持显式循环。

此外,我认为map()filter()通常不会被认可。相反,通常列表推导似乎是首选。

答案 4 :(得分:5)

StackOverflow上的大多数答案都是简短,简洁的答案,而python的功能方面使得编写这类答案变得容易。

Python的OO功能在10-20行答案中根本不需要,所以你不会在这里看到它们。

答案 5 :(得分:1)

当我处理一个能很好地映射到OO解决方案的问题时,我会选择Python。与完整的函数式语言相比,Python仅提供有限的功能编程能力。

如果我真的想要函数式编程,我使用Lisp。