我们如何将“functools.partial”转换为装饰器?

How can we transform `functools.partial` into a decorator?

提问人:Toothpick Anemone 提问时间:9/18/2022 更新时间:9/18/2022 访问量:135

问:

库中有一个名为 的工具。functoolspartial

functools.partial允许我们将某些输入指定为函数,而无需指定所有输入。

你可以转换...

变成类似的东西......
funky_function(x1, x2, x3, x4, x5)
funky_function(1, 2, x3, x4, x5)

那是。。。

  • 输入参数被分配数字x11
  • 输入参数被分配数字x22
  • 输入 , , 仍分配任何内容。x3x4x5
from functools import *
from inspect import *

def funky_function(x1, x2, x3, x4, x5, /):
    return ", ".join(" ".join(str(x).split()) for x in [x1, x2, x3, x4, x5])

funky_function = partial(funky_function, 1, 2)

result = funky_function(3, 4, 5)

print("return value from `funky_function(3, 4, 5)` is:", result)
print("signature of `funky_function` is:", signature(funky_function))

我的问题是,我们如何制作装饰器?

@partialize(1, 2)
def funky_function(x1, x2, x3, x4, x5, /):
    return ", ".join(" ".join(str(x).split()) for x in [x1, x2, x3, x4, x5])

result = funky_function(3, 4, 5)

请看下面的函数签名:partial.partial(func)

functools.partial(func, /, *args, **keywords)

函数在左边,参数在右边。

以下两段代码是等效的:

@decorate(1, 2)
def f():
   pass
###################################
def f():
   pass
f = decorate(1, 2)(f)

因此,如果您想先输入参数,然后输入函数,则不是一个好的装饰器。partial

我们如何制作一个装饰器,它首先接受参数,然后接受要装饰的函数?

python-3.x 参数传递 装饰器 签名

评论

1赞 philosofool 9/18/2022
我有点困惑:你为什么要写一个有 N 个参数的函数,然后装饰它,让一些变得无关紧要?在我看来,如果你想要这样的东西,你会先写再写def main_func(x1, x2, ... xn): ...def func(...): return main_func(<relevant params>)
0赞 Toothpick Anemone 9/18/2022
@philosofool 一个潜在的应用(但不是唯一的应用)是在定义函数时使用变量的值,而不是在调用函数时使用变量的值。例如,您可以修饰一个函数,以便将其作为输入传入,其中我们使用函数定义之前的值,而不是在调用函数时很久以后的值。radiusradiusradius

答:

1赞 Toothpick Anemone 9/18/2022 #1

类似于以下工作:

from functools import *
from inspect import *

def partialize(*args, **kwargs):
    def partialize_helper(old_func):
        new_func = partial(old_func, *args, **kwargs)
        return new_func
    return partialize_helper

@partialize(1, 2)
def funky_function(x1, x2, x3, x4, x5, /):
    return ", ".join(" ".join(str(x).split()) for x in [x1, x2, x3, x4, x5])

##########################################################################

funky_function = partialize(1, 2)(funky_function)

##########################################################################

result = funky_function(3, 4, 5)
print("valued returned by funky_function(3, 4, 5)".ljust(50), result)
print("str(funky_function) ==".ljust(50), str(funky_function))
print("Signature == ".ljust(50), signature(funky_function))

控制台输出如下:

valued returned by funky_function(3, 4, 5)         1, 2, 3, 4, 5
str(funky_function) ==                             functools.partial(<function funky_function at 0x000001C99759E200>, 1, 2)
Signature ==                                       (x3, x4, x5, /)