首页 > 解决方案 > Python装饰函数保留部分签名

问题描述

我写了以下装饰器:

def partializable(fn):
    def arg_partializer(*fixable_parameters):
        def partialized_fn(dynamic_arg):
            return fn(dynamic_arg, *fixable_parameters)

        return partialized_fn
    return arg_partializer

这个装饰器的目的是将函数调用分成两个调用。如果我装饰以下内容:

@partializable
def my_fn(dyn, fix1, fix2):
    return dyn + fix1 + fix2

然后我可以这样做:

core_accepting_dynamic_argument = my_fn(my_fix_1, my_fix_2)
final_result = core_accepting_dynamic_argument(my_dyn)

我的问题是现在装饰my_fn的显示以下签名:my_fn(*fixable_parameters)

我希望它是:my_fn(fix1, fix2)

我怎样才能做到这一点?我可能必须使用wrapsordecorator模块,但我只需要保留原始签名的一部分,我不知道这是否可能。

标签: pythonpython-decorators

解决方案


https://stackoverflow.com/a/33112180/9204395获得灵感,可以通过手动更改 的签名来完成此操作arg_partializer,因为在相关范围内只有 的签名fn是已知的并且可以使用inspect.

from inspect import signature

def partializable(fn):
    def arg_partializer(*fixable_parameters):
        def partialized_fn(dynamic_arg):
            return fn(dynamic_arg, *fixable_parameters)

        return partialized_fn

    # Override signature
    sig = signature(fn)
    sig = sig.replace(parameters=tuple(sig.parameters.values())[1:])
    arg_partializer.__signature__ = sig

    return arg_partializer

这不是特别优雅,但当我想到这个问题时,我开始怀疑这(或概念上的等价物)是实现这一特技的唯一可能方法。随意反驳我。


推荐阅读