偏函数-functools之partial

前段时间在讲述 Flask-Login 的源码中遇见了一个函数 ——partial,这个函数来自于functools模块,这个模块定义为”The functools module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for the purposes of this module”,翻译成中文的大概意思就是”functools 用于高阶函数:指那些作用于函数或者返回其他函数的函数。总的来说,这个模块的目标就是将任何可调用的对象都可以被视为函数。”

functools.partial

返回一个新的部分对象,当被调用的时候,相当于原有的对象携带了默认的参数.如果在调用过程中传递了更多的参数,将会被追加到args.如果提供了其他的关键字参数,则会覆盖或者扩展关键字:

1
2
3
4
5
6
7
8
9
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc

当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单.

eg:

int()函数,可以将字符串转为整数,简单看一下它的函数使用说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class int(object)
| int(x=0) -> integer
| int(x, base=10) -> integer
|
| Convert a number or string to an integer, or return 0 if no arguments
| are given. If x is a number, return x.__int__(). For floating point
| numbers, this truncates towards zero.
|
| If x is not a number or if base is given, then x must be a string,
| bytes, or bytearray instance representing an integer literal in the
| given base. The literal can be preceded by '+' or '-' and be surrounded
| by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
| Base 0 means to interpret the base from the string as an integer literal.
| >>> int('0b100', base=0)
| 4

从上述说明中我们可以看见,int还有一个额外的参数base,base 默认值为10,也就意味着默认情况下将字符串转化为十进制的数.如果我们需要转化成二进制怎么办?在不使用其他模块的情况下,只需要int(x,base=2),那么如果是借助partial,该如何使用呢?

1
2
3
4
5
6
7
8
9
10
>>>from functools import partial
>>>int2 = partial(int,base=2) # 这里是传递了关键字参数,即keywords
>>>int2('1000')
>>>8
>>>str_3_int = partial(int,'3') # 传递了参数args
>>>str_3_int()
>>>3 # 不够清楚的话可以接着看下面的例子
>>>max_with_10 = partial(max,10)
>>>max_with_10(2,3,4)
>>>10