柯里化与偏函数

举报
子都爱学习 发表于 2021/10/20 19:51:13 2021/10/20
【摘要】 偏函数(partial)和函数柯里化(currying)是函数式编程中常用的技术。有时候我们在复用已有函数时可能需要固定其中的部分参数,这除了可以通过默认值参数来实现之外,还可以使用偏函数。我们定义一个函数:def add(x: int, y=5): return x + y调用 --> add(3, 4)柯里化后:# 柯里化def newadd(x): def wrapper(...

偏函数(partial)和函数柯里化(currying)是函数式编程中常用的技术。有时候我们在复用已有函数时可能需要固定其中的部分参数,这除了可以通过默认值参数来实现之外,还可以使用偏函数。

我们定义一个函数:

def add(x: int, y=5):
    return x + y

调用 --> add(3, 4)

柯里化后:

# 柯里化
def newadd(x):
    def wrapper(y):
        return x + y
    return wrapper

调用 --> add(3)(4)

偏函数:

from functools import partial

newadd1 = partial(add, 3)
newadd1(4)
# 7


newadd2 = partial(add, y=5)
newadd2(2)
# 7

newadd2(3, y=4)
# 7

newadd2(3, 5)
# add() got multiple values for argument 'y'

newadd2(3, 5, y=4)
# add() got multiple values for argument 'y'

可能这样看,不太好理解,我们打印下签名

import inspect

inspect.signature(newadd1)
# (y=5)

inspect.signature(newadd2)
# (x: int, *, y=5)

然后 help() 查看一下:

help(partial)

# 有这样一句话:new function with partial application of the given arguments and keywords.
理解就是:对一个函数的部分参数固定,从而返回一个新包装函数,这个函数应该是关于剩余参数的一个函数

查看源码我们也可以看到(3.7后partial用类来实现,原理也是差不多)

# partial 等价
def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = {**keywords, **fkeywords}
        ret = func(*args, *fargs, **newkeywords)
        return ret
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

偏函数使用非常广泛,比如装饰器 @wraps 

def logger(wrapped):
    @wraps(wrapped)  # wrapper = wraps(wrapped)(wrapper)
    def wrapper(*args, **kwargs):  # wrapper.__wrapped__ = wrapped
        return wrapped(*args, **kwargs)
    return wrapper

def logger_equ(wrapped):
    def wrapper(*args, **kwargs):
        return wrapped(*args, **kwargs)
    update_wrapper(wrapper, wrapped)
    return wrapper

实现使用了partial

# 实例 装饰器中 @wraps 中的实现使用了 partial
def wraps(wrapped,
          assigned=WRAPPER_ASSIGNMENTS,
          updated=WRAPPER_UPDATES):
    return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。