什么是偏函数
偏函数应用(Partial Function Application)听起来名字就很吸引人;它的作用是在函数调用前,预先固定参数的方法。它的机制有点粗糙,学术的解释有点古板,但是它很有用。如果你的函数需要 x
和 y
两个参数,实现把 x
参数固定了,后续调用只需要传入 y
即可,来看一个例子:
# -*- coding: utf-8 -*-
import functools
def adder(x, y):
return x + y
# 执行它
assert adder(1, 1) == 2
assert adder(5, 5) == 10
assert adder(6, 2) == 8
# 把 y 的参数固定
add_five = functools.partial(adder, y=5)
# 现在 加上 5
# x =1, y =5
assert add_five(1) == 6
# x =5, y =5
assert add_five(5) == 10
# x =2, y =5
assert add_five(2) == 7
坦白说,这个例子并没什么用处,但也不是一无是处。至少它很好展示了偏函数应用的用法。但是并没有告诉你为什么要用它,或者哪里能使用它。当你开始使用函数开始编写程序的时候,你很难从这个例子来想象他的使用场景。
这就是我为什么写这篇博客原因。我想要尝试不一样的方式。因为其他人已经把偏函数应用的实现机制都写烂了,我将跳过这个部分,旨在阐述它的应用场景。我们通过案例学习;每个案例的讲解都会通过逐步重构来有效应用偏函数。
案例1 - 重构特定领域表达式
我经常使用编写任务匹配的应用;如追踪 URL,查找制定循环,在日志文件中寻找模式。这类的任务,会慢慢变的臃肿,最终会失去控制。
导致这个问题的罪魁祸首就是正则表达式。没有任何的警惕,给予足够的时间,和不断增多的 “呃,你还能找到。。。” 方式请求,它很快就让你陷入不可维护代码的深坑。比如:
for text in lines:
if re.search(‘[a-zA-Z]\=’, text):
some_action(text)
elif re.search(‘[a-zA-Z]\s\=’, text):
some_other_action(text)
else:
some_default_action()
当我们需要快速实现的时候,这样看起来没什么问题。然后,几周之后再来看这段代码,我已经看不懂这代码中正则表达式的含义了。因此,是时候开始重构了。第一步就是拨出不合理的部分,利用良好命名的函数来替换我们的正则表达式:
def is_grouped_together(text):
return re.search("[a-zA-Z]\s\=", text)
def is_spaced_apart(text):
return re.search(