我看到StackOverflow上的大多数Python开发人员认可使用简洁的功能工具,如lambdas,地图,过滤器等,而其他人则认为他们的代码更清晰,更易于维护而不使用它们。你有什么偏好?
另外,如果你是一个顽固的功能程序员或OO的硬核,你认为哪种其他特定的编程实践最适合你的风格?
提前感谢您的意见!
答案 0 :(得分:48)
我主要使用Python使用面向对象和程序样式。 Python实际上并不特别适合函数式编程。
许多人认为他们使用大量lambda
,map
,filter
和reduce
编写功能性Python代码,但这有点过了 - 简化。功能编程的标志性特征是缺乏状态或副作用。功能样式的重要元素是纯函数,递归算法和第一类函数。
以下是我对函数式编程和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())
和类似的东西。这避免了将相同列表对象存储在别处并且不应更改的错误。 (如果 应该更改,那么你很可能会遇到设计错误。改变一些你引用多个地方的列表并不是分享状态的好方法。)
< / LI> 不要无偿地使用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
。匿名函数并不比命名函数更好,后者通常更健壮,可维护,并记录在案。
答案 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。