说我有一些函数fun
,其实际代码主体不在我的控制范围内。我可以创建一个新函数,该函数在调用fun
之前进行一些预处理,即
def process(x):
x += 1
return fun(x)
如果我现在希望process
代替fun
来以后所有对fun
的呼叫,我需要做类似的事情
# Does not work
fun = process
但是,这不起作用,因为这会产生一个循环引用问题,因为现在fun
的主体内部已调用fun
。我发现一种解决方案是在fun
内引用process
的副本,如下所示:
# Works
import copy
fun_cp = copy.copy(fun)
def process(x):
x += 1
return fun_cp(x)
fun = process
但是这个解决方案使我感到困扰,因为我真的不知道Python如何构造函数的副本。我猜我的问题与使用继承和super
函数扩展类方法的问题相同,但是在这里我没有类。
如何正确执行此操作?我认为这是一项足够常见的任务,应该或多或少有一些惯用的解决方案,但是我没有运气找到它。
答案 0 :(得分:1)
这看起来像是python闭包的用例。有一个函数返回您的函数。
android studio
答案 1 :(得分:1)
Python不是 构造函数的副本。 copy.copy(fun)
仅返回fun
;区别在于您将其保存到fun_cp
变量中,该变量与您保存process
的变量不同,因此当fun_cp
尝试查找时,它仍在process
中它。
我将执行与您所做的类似的操作,将原始函数保存到其他变量中,而无需添加“ copy”:
original_fun = fun
def fun(x):
x += 1
return original_fun(x)
如果要将相同的包装应用于多个功能,则定义装饰器并执行fun = decorate(fun)
更可重用,但是一次性执行则比必要的工作更多,而且缩进程度更高。
答案 2 :(得分:0)
使用闭包的想法向Coldspeed致谢。一个完整的工作和完善的解决方案是
%PDF-1.4
1 0 obj
<<
/Title (��)
/Creator (��)
/Producer (��Qt 5.5.1)
/CreationDate (D:20180916225804)
>>
endobj
2 0 obj
<<
/Type /Catalog
/Pages 3 0 R
>>
endobj
4 0 obj
请注意,这等同于将装饰器(import functools
def getprocess(f):
@functools.wraps(f)
def process(x):
x += 1
return f(x)
return process
fun = getprocess(fun)
)应用于getprocess
100%。我无法提出这种解决方案,因为专用装饰器语法fun
仅可在函数的定义位置(此处为@getprocess
)使用。要将其应用于现有功能,只需执行fun
。