FP不仅对并发性很重要;事实上,在规范的Python实现中几乎没有并发性(也许3.x会改变这一点?)。在任何情况下,FP很适合并发,因为它导致程序没有或更少(显式)状态。各州的麻烦有几个原因。一个是它们使计算的分布变得困难(er)(这是并发性的论点),另一个,在大多数情况下更重要的是,这是造成错误的倾向。当代软件中最大的缺陷源是变量(变量和状态之间有着密切的关系)。FP可以减少程序中变量的数量:除掉bug!在
看看在这些版本中混合变量会引入多少错误:def imperative(seq):
p = 1
for x in seq:
p *= x
return p
vs(警告,my.reduce的参数列表与python的reduce的参数列表不同;后面给出了基本原理)
^{pr2}$
正如你所看到的,事实上,FP给了你更少的机会用一个与变量相关的bug来攻击自己。在
另外,可读性:它可能需要一些训练,但是functional比imperative更容易阅读:你可以看到reduce(“好吧,它将一个序列减少为一个值”),mul(“通过乘法”)。其中imperative具有for循环的一般形式,充满了变量和赋值。这些for循环看起来都一样,所以要想知道imperative中发生了什么,你需要阅读几乎所有的内容。在
还有简洁和灵活。你给我imperative,我告诉你我喜欢它,但也需要一些对序列求和的东西。没问题,你说,然后你去复制粘贴:def imperative(seq):
p = 1
for x in seq:
p *= x
return p
def imperative2(seq):
p = 0
for x in seq:
p += x
return p
如何减少重复?好吧,如果运算符是值,你可以做如下操作def reduce(op, seq, init):
rv = init
for x in seq:
rv = op(rv, x)
return rv
def imperative(seq):
return reduce(*, 1, seq)
def imperative2(seq):
return reduce(+, 0, seq)
哦等等!operators提供了是值的运算符!但是。。亚历克斯·马泰利已经谴责了。。。看起来如果你想保持在他建议的范围内,你注定要复制粘贴管道规范。在
FP版本更好吗?当然你也需要复制粘贴吗?在import operator as ops
def functional(seq):
return my.reduce(ops.mul, 1, seq)
def functional2(seq):
return my.reduce(ops.add, 0, seq)
好吧,那只是半途而废的方法的产物!放弃命令式def,您可以将两个版本收缩为import functools as func, operator as ops
functional = func.partial(my.reduce, ops.mul, 1)
functional2 = func.partial(my.reduce, ops.add, 0)
甚至是import functools as func, operator as ops
reducer = func.partial(func.partial, my.reduce)
functional = reducer(ops.mul, 1)
functional2 = reducer(ops.add, 0)
(func.partial是my.reduce的原因)
运行速度呢?是的,在Python这样的语言中使用FP会产生一些开销。在这里,我就照搬一些教授对此的看法:过早的优化是万恶之源。在
大多数程序在20%的代码中花费了80%的运行时间。在
侧写,不要猜测!在
我不太擅长解释事情。别让我把水弄得太浑浊,读一下约翰·巴克斯在1977年获得图灵奖时所作的前半部分。引用:5.1 A von Neumann Program for Inner Productc := 0
for i := I step 1 until n do
c := c + a[i] * b[i]
Several properties of this program are
worth noting:Its statements operate on an invisible "state" according to complex
rules.
It is not hierarchical. Except for the right side of the assignment
statement, it does not construct
complex entities from simpler ones.
(Larger programs, however, often do.)
It is dynamic and repetitive. One must mentally execute it to
understand it.
It computes word-at-a-time by repetition (of the assignment) and by
modification (of variable i).
Part of the data, n, is in the program; thus it lacks generality and
works only for vectors of length n.
It names its arguments; it can only be used for vectors a and b.
To become general, it requires a
procedure declaration. These involve
complex issues (e.g., call-by-name
versus call-by-value).
Its "housekeeping" operations are represented by symbols in
scattered places (in the for statement
and the subscripts in the assignment).
This makes it impossible to
consolidate housekeeping operations,
the most common of all, into single,
powerful, widely useful operators.
Thus in programming those operations
one must always start again at square
one, writing "for i := ..." and
"for j := ..." followed by
assignment statements sprinkled with
i's and j's.
本文主要探讨Python中函数式编程(FP)的优势。FP适合并发,能减少程序中变量数量以降低出错率;具有更好的可读性,比命令式编程更易理解;还具备简洁和灵活的特点,可减少代码重复。虽在Python中使用FP有开销,但不应过早优化。

被折叠的 条评论
为什么被折叠?



