1、引言
Python作为一种强类型动态语言,拥有丰富的函数式编程特性。其中一个特点是支持偏函数——partial函数。这恰好可以解决我们常常遇到的“非固定参数”问题。关于这个,我们先从一个例子入手:
def power(x, y): return x**y print(power(2, 3)) # 输出8 print(power(2, 4)) # 输出16
在这个例子中,我们定义了一个求幂的函数,但是某一次我们需要默认计算2的平方,这种情况下我们可以直接调用 power(2, 2)
。这时候,如果你的代码里有大量这个样子的情况,你肯定不想在每个函数里都写 2, 2
。
那么我们怎么办呢?
这时候就需要partial函数了。
2、partial函数的基本用法
1) partial函数的起源
我们有这么一个场景:我们需要对一个列表里所有的数字进行乘以2,然后再加1的操作,得到新的列表。
lst = [0, 1, 2, 3] new_lst = [(x * 2 + 1) for x in lst] print(new_lst) # 输出[1, 3, 5, 7]
在上面的例子中,我们不仅写起来很麻烦,而且还写出了一堆冗长的代码,难以维护。这时候我们需要partial函数的出现。
2) partial函数的定义
Python的functools模块提供了一个叫做partial的函数,它可以帮助我们创建偏函数。那么,什么是偏函数呢?
偏函数是函数式编程中的一个概念,它可以把一个函数的某些参数给固定住,返回一个新的函数,简化原函数的调用。在调用新函数的时候,只需要传入未曾固定的参数即可。
为了更好地理解,我们下面通过一些例子来逐步探究partial函数的用法。
3) partial函数的第一个例子
实际上,在第一个例子中,我们已经使用了类似偏函数的思想。题目要求我们对a列表中的所有数乘以3,所以我们写出了下面的代码:
a = [1, 2, 3, 4, 5] b = list(map(lambda x: x * 3, a)) print(b) # 输出[3, 6, 9, 12, 15]
在使用lambda表达式的时候,我们把x * 3
作为参数传给了map()函数,使用了函数式编程的思想。
而使用partial函数,我们就可以使用更为简洁的方式把参数固定下来:
from functools import partial def multiply(a, b): return a * b times_three = partial(multiply, b=3) print(times_three(2)) # 输出6
在上面的例子中,我们把multiply函数中的b参数固定为3,得到了一个新函数times_three。我们后续只需要传入a参数即可。
4) partial函数的第二个例子
接下来,我们将继续了解partial函数的应用。我们再来看一个例子。假设有一个函数:
def calculate(a, b, c, d): return a + b + c - d
我们现在需要调用一个函数,它的第一个参数是5,剩余的参数是calculate()函数的剩余参数。
如果我们使用标准的调用,代码会变得非常冗长:
calculate_params = (6, 7, 8) result = calculate(5, *calculate_params, 2) print(result) # 输出24
这里,我们原本需要传递5,6,7,8和2这几个参数。但是,为了让代码的可读性更高,我们尝试使用partial函数,重构代码:
calculate_params = (6, 7, 8) partial_calculate = partial(calculate, 5, *calculate_params) result = partial_calculate(2) print(result) # 输出24
在上面的例子中,我们利用了partial函数把calculate()函数中前两个参数的值固定为5和6。
由此,我们可以看到,partial函数可以大大提高我们代码的可读性,使得代码更加简洁和易于维护。接下来,我们将介绍partial函数的高级用法。
3、partial函数的高级用法
1) 通过partial函数改变函数的行为
在实际应用中,有时候我们需要使用partial函数来改变原函数的行为,可以实现更加多样化的功能。
我们通过一个例子来说明这种用法:
from functools import partial def calculate(a, b, c, d): return a + b + c - d difference = partial(calculate, d=0) # 固定d参数为0 print(calculate(1, 2, 3, 4)) # 输出2 print(difference(1, 2, 3)) # 输出6
在上面的例子中,我们调用了partial函数,把calculate()函数中的d参数固定为0。
但是如果我们愿意,我们还可以把这个新的函数的参数再一次固定住,例如:
difference = partial(calculate, b=2, d=0) print(difference(1, 3)) # 输出6
在这个例子中,我们把calculate()函数中的b和d参数均固定为特定的值,得到了一个新的函数difference。我们可以仅传递2个参数调用它,而不用考虑其他参数的值。
2) 通过partial函数改变函数签名
有些时候,我们需要改变函数签名,以达到某种目的。在Python中,我们可以使用partial函数完成这种需求。
下面,我们来看一个例子,它能够帮助我们更好地理解partial函数如何改变函数签名:
from functools import partial def calculate(a, b=0, c=0, *, d=1, e=1): return a + b + c - d + e new_calculate = partial(calculate, e=2) print(new_calculate(1, 2)) # 输出2
在上面的例子中,我们调用了partial函数,并且把e参数固定为2。此时,新的函数new_calculate()的签名变成了:
signature(new_calculate) # 输出inspect.Signature(parameters=[, , , ])
由此,我们可以看出, partial函数可以改变函数的参数签名,以实现更加灵活的功能。
3) 将可调用对象转换为函数
有的时候,可能需要将一个自定义的可调用对象转换为函数对象,以方便使用。在Python中我们可以使用partial函数来实现这一目的。
简单来说,如果一个对象不是一个函数对象,那么partial函数可以将其转换成函数对象。在这种情况下,这个对象被看作是一个调用对象,它可以调用,但是不具备函数的特性。这时候,我们需要借助partial函数帮助我们实现高级特性。
接下来,我们通过一个例子探究如何把可调用对象转换成函数对象。
from functools import partial class Operations: def __init__(self, a, b): self.a = a self.b = b def add(self): return self.a + self.b def mul(self): return self.a * self.b op = Operations(5, 6) print(op.add()) # 输出11 print(op.mul()) # 输出30 add_op = partial(op.add) # 转换成函数 print(add_op()) # 输出11
在上面的例子中,我们定义了一个Operations类,并且为其添加了add和mul两个方法。
接下来,我们使用partial函数把其中一个方法转换成函数,并且实现了调用,成功得到了输出结果。
4、结论
总的来说,Python中的partial函数是一个十分有用的工具,它可以提高我们编写代码的可读性和代码的维护性。
partial函数有丰富的用法,可以通过对参数进行固定,让我们的代码更加简洁;也可以改变函数的签名以支持更高级的特性;还可以把可调用对象转换成函数对象以方便使用。
在实际工作中,我们可以结合实际的应用需求,充分了解partial函数的用法,发挥其巨大的价值和作用。希望本文可以帮助大家更好地了解partial函数的用法和应用场景。