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

Eri*_*ric 29 python oop functional-programming

我看到StackOverflow上的大多数Python开发人员都赞同使用lambda,map,filter等简洁的功能工具,而其他人则认为他们的代码更清晰,更易于维护而不使用它们.你有什么偏好?

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

在此先感谢您的意见!

Mik*_*ham 53

我主要使用面向对象和程序样式的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]
      
      Run Code Online (Sandbox Code Playgroud)

      而不是

      for index, _ in enumerate(foo):
          foo[index] = bar(foo[index].baz())
      
      Run Code Online (Sandbox Code Playgroud)

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

  • 不要map无偿地和朋友一起使用.这样做没有什么更多功能.

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

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


Ign*_*ams 23

我使用语言的功能,使用最短,最干净的代码完成工作.如果这意味着我必须混合我经常做的两个,那就是完成了.


Joc*_*zel 8

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

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

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

Python中的FP主要围绕编写生成器及其亲属(列表推导)和itertools模块中的内容.只需要显式map/filter/reduce调用.


sth*_*sth 6

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

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

  • 请注意,列表推导来自功能世界,就像`map`和`filter`一样. (3认同)

tst*_*ner 5

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

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