Eri*_*ric 29 python oop functional-programming
我看到StackOverflow上的大多数Python开发人员都赞同使用lambda,map,filter等简洁的功能工具,而其他人则认为他们的代码更清晰,更易于维护而不使用它们.你有什么偏好?
另外,如果你是一个顽固的功能程序员或OO的硬核,你认为哪种其他特定的编程实践最适合你的风格?
在此先感谢您的意见!
Mik*_*ham 53
我主要使用面向对象和程序样式的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]
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是比列表理解更难理解.我永远不会使用map或filter使用lambda,但如果我有一个已经存在的功能可能会; 我使用map了一点点.itertools.imap/ ifilter比较.(这些东西有点懒,这是我们可以从功能世界中借鉴的东西.)map和filter副作用.我map经常看到这一点,这些都使得难以理解的代码,不需要的列表,并且显然不起作用(尽管人们认为它必须是因为map.)只需使用for循环.reduce除非是非常简单的案例,否则令人困惑.Python有for循环,使用它们没有任何伤害.不要使用递归算法.这是函数式编程的一部分,Python不能很好地支持.CPython(我认为所有其他Pythons)都不支持尾调用优化.请改用迭代.
仅lambda在您动态定义函数时使用.匿名函数并不比命名函数更好,后者通常更健壮,可维护和记录.
我既是一个顽固的OOP和功能程序员,这些风格很好地协同工作,主要是因为它们是完全正交的.有很多面向对象的函数式语言,Python就是其中之一.
所以基本上,在设计系统时,将应用程序分解为类非常有用.当您进行实际实现时,FP有助于编写正确的代码.
另外我觉得非常冒犯你暗示功能性编程只是意味着"在任何地方使用折叠".这可能是关于FP的最大和最坏的误解.关于该主题已经写了很多,所以我只想说FP的优点是将简单(,正确和可重用)函数组合成新的,越来越复杂的函数.这样就很难编写"几乎正确"的代码 - 要么整个事情完全符合您的要求,要么完全破坏.
Python中的FP主要围绕编写生成器及其亲属(列表推导)和itertools模块中的内容.只需要显式map/filter/reduce调用.
Python只有边缘函数编程功能,所以如果很多人特别使用它,我会感到惊讶.例如,没有标准的方法来执行函数组合,并且reduce()已经弃用了标准库以支持显式循环.
此外,我不认为map()或filter()一般认可.相反,通常列表推导似乎是首选.
StackOverflow上的大多数答案都是简短,简洁的答案,而python的功能方面使得编写这类答案很容易.
Python的OO功能在10-20行答案中根本不需要,所以你不会在这里看到它们.