python functools.partial 的理解

首先我们看看官方文档的定义:
Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords.

  1. If more arguments are supplied to the call, they are appended to args.
  2. If additional keyword arguments are supplied, they extend and override keywords. Roughly equivalent to:
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

我们一步一步的读:

  1. 闭包定义了一个新的函数newfunc,有2个参数签名fargs和fkeywords。这个newfunc的函数体很简单,就是把partial函数的参数和newfunc函数的参数合并起来给partial函数的第一个参数func函数执行,返回执行后的结果。
  2. 把partial函数的参数属性赋值给newfunc
  3. 返回newfunc

简单的示例说明:

from functools import partial
def add(x, y, z):
    return x + y + z

a1 = partial(add, 10, 20)
# 60
print(a1(30))

# functools.partial(, 10, 20)
print(a1)

分部解释:

  1. partial函数的参数:func=add,args=(10, 20)
  2. 通过获得partial的返回值:a1 = partial(add, 10, 20)。把返回的newfunc赋值给了a1,则执行a1(30) 与 add(*(10, 20), 30)等价。

复杂的示例说明:
如果我的partial函数第二值传的是个函数,会发生什么事情呢?看如下示例。

def sub(x, y):
    return x - y

def div(x, y):
    return x/y

def attach_wrap(func1, func2=None):
    if func2 is None:
        return partial(attach_wrap, func1)
    setattr(func1, func2.__name__, func2)
    return func1

sub1 = attach_wrap(sub)
print(sub1)

sub2 = sub1(div)
print(sub2)

print(sub2(20, 10)) //10
print(sub2.div(20, 10)) //2.0

解释说明:

  1. attach_wrap(sub)执行,发现func2为None,所以执行if语句: partial(attach_wrap, func1)的返回相当于:
  2. sub1 = attach_wrap(*(func1), *fargs, **fkwargs)
  3. 调用sub1(div),这时候func2为div函数,所以把func2设置为func1的属性
  4. 返回func1,结果就是func1绑定了func2函数

上面的这种写法经常可以用来在一个函数上绑定另一个函数:

def sub(x, y):
    return x - y

def attach_wrap(func1, func2=None):
    if func2 is None:
        return partial(attach_wrap, func1)
    setattr(func1, func2.__name__, func2)
    return func1

@attach_wrap(sub)
def div(x, y):
    return x/y

print(sub(10, 5))
print(sub.div(10, 5))

你可能感兴趣的:(Python)