Functional Programming in Python
什么是函数式编程?
Functional programming is what you do when you program in languages like
Lisp, Scheme, Clojure, Scala, Haskell, ML, OCAML, Erlang, or a few others.
函数式编程的特点
函数是一等公民
例如你可以把一个函数作为参数传给另一个函数
任何对数据的操作都适用于函数
举个例子——装饰器的实现
递归被用作主要的结构控制
是没有循环的
对于某些语言而言
并不适用于 Python...
强大的列表处理能力
多级嵌套的列表与递归一起取缔了循环
在Python中:
- Python对列表的操作很灵活,包括很多强大的内建方法、标准库以及第三方库。
- 其本身并未做递归优化,所以总有许多循环的过程,是这些强大的列表操作无法替代的。
- 在多数情况下,推荐使用列表推导来代替map和filter,因为效率上列表推导更胜一筹。(zip and reduce is good ^_^)
无副作用(放心食用)
在纯粹的函数式编程语言(例如Haskell)中,变量不可变:
你无法声明并赋值一个数据结构,
然后再在之后的程序流中改变它。
在Python中:
- 死心吧,这是不可能的。
- 不过你可以通过描述符来拒绝对象属性的变更。
- 当你想要改变时,返回一个新的深拷贝对象(通过函数获取新的数据结构)。
没有状态
使用表达式求值来代替“状态”。
在纯粹的函数式编程语言里,一个程序即是一个表达式。
在Python中:
- 可以实现,但是大多数情况下不推荐这么做。
- 取舍,一般取决于是否增加了可读性。
实体重于过程
这是个哲学问题...请参考后面的例子。
函数式编程语言更关注什么要被计算,
而不是它如何被计算。
高阶函数
Python支持将函数当成普通对象来处理,所以
你懂的...
简单而言,就是一种操作操作其他函数的函数的函数。
吐槽:这个函数式编程特性混入了奇怪的东西...
Examples
Good
原版
FP
安全的闭包
class Adder(object):
def __init__(self, n):
self.n = n
def __call__(self, m):
return self.n + m
add5_i = Adder(5)def make_adder(n):
def adder(m):
return m+n
return adder
add5_f = make_adder(5)>>> add5_i(10)
15
>>> add5_f(10)
15
>>> add5_i.n = 10 # 状态改变
>>> add5_i(10) # 结果随程序流而改变,不安全!
20食用
FP版本也不是完全安全的吗?
# 一个坑
>>> adders = []
>>> for n in range(5):
adders.append(lambda m: m+n)
>>> [adder(10) for adder in adders]
[14, 14, 14, 14, 14]
>>> n = 20
>>> [adder(10) for adder in adders]
[30, 30, 30, 30, 30]
# 什么鬼?
# --Python并不是纯粹的函数式编程语言,
# 变量的状态改变时有发生!
# 解决方案(默认参数)
>>> adders = []
>>> for n in range(5):
adders.append(lambda m, n=n: m+n)
>>> [adder(10) for adder in adders]
[10, 11, 12, 13, 14]
# 其实完全安全是可以做到的
# 因为我们有 Plan B
>>> from operator import add
>>> from functools import partial
>>> adders = []
>>> for n in range(5):
adders.append(partial(add, n))
# thanks to 严波老师
# 是他告诉我 partial 这么个好玩的东西# 然而还是存在一个小隐患,你可以重载绑定的默认参数
>>> add4 = adders[4]
>>> add4(10, 100)
110Bad
原版(Good)
FP(Bad)
def factorialR(N):
"Recursive factorial function"
assert isinstance(N, int) and N >= 1
return 1 if N <= 1 else N * factorialR(N-1)def factorialI(N):
"Iterative factorial function"
assert isinstance(N, int) and N >= 1 product = 1
while N >= 1:
product *= N
N-=1
return productBest
from operator import mul
def factorialHOF(n):
return reduce(mul, range(1, n+1), 1)计
算
阶
乘
递归更好实现的算法
快速排序
worst
# 正常版本的qsort
def qsort(lst, cmp):
if len(lst) <= 1:
return lst
pivot = lst[0]
pivots = filter(lambda x: cmp(x, pivot) == 0, lst)
small = qsort(filter(lambda x: cmp(x, pivot) < 0, lst), cmp)
large = qsort(filter(lambda x: cmp(x, pivot) > 0, lst), cmp)
return small + pivots +large# 精神病患者的qsort
def qsort2(lst, cmp):
def filter_cmp(f, x): return f(cmp(x, lst[0]), 0)
return lst if len(lst) <= 1 else sum(map(lambda op: filter(partial(filter_cmp, op), lst) \
if op is eq else qsort2(filter(partial(filter_cmp, op), lst), cmp), [lt, eq, gt]), [])Sum up
语言是实现思想的工具,
所以 范式 和 库、设计模式 之流的功能相似,
只是为了让我们更方便地实现罢了。
Thanks for Whatching
Bonus
- operator
-
functools
-
itertools
-
pyrsistent
-
toolz
-
hypothesis
-
more_itertools
Functional Programming in Python
By magine
Functional Programming in Python
2015年8月13日,豆瓣北郡分享会。
- 451