Python:重新定义函数,以便它引用自己的自身

问题描述 投票:1回答:3

说我有一些函数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函数扩展类方法的问题相同,但在这里我没有类。

我该怎么做呢?我认为这是一个足够普遍的任务,应该存在一些或多或少的惯用解决方案,但我找不到运气。

python python-3.x function reference functional-programming
3个回答
1
投票

Python没有构建函数的副本。 copy.copy(fun)刚刚返回fun;区别在于你将它保存到fun_cp变量,这是一个与你保存process的变量不同的变量,所以当fun_cp试图寻找它时它仍然在process

我会做类似于你所做的事情,将原始函数保存到另一个变量,只是没有“复制”:

original_fun = fun
def fun(x):
    x += 1
    return original_fun(x)

如果你想将相同的包装应用于多个函数,定义装饰器和执行fun = decorate(fun)更具有可重用性,但对于一次性,它需要的工作量超过必要性和额外的缩进级别。


1
投票

这看起来像python的闭包的用例。有一个功能返回你的功能。

def getprocess(f):
    def process(x):
        x += 1
        return f(x)  # f is referenced from the enclosing scope.

    return process

myprocess = getprocess(fun) 
myprocess = getprocess(myprocess) 

0
投票

感谢coldspeed使用闭包的想法。一个完全工作和抛光的解决方案是

import functools

def getprocess(f):
    @functools.wraps(f)
    def process(x):
        x += 1
        return f(x)
    return process

fun = getprocess(fun)

请注意,这相当于将装饰器(getprocess)应用于fun。我无法想出这个解决方案,因为专用的装饰器语法@getprocess只能在函数的定义位置使用(这里是fun)。要将其应用于现有功能,请执行fun = getprocess(fun)

© www.soinside.com 2019 - 2024. All rights reserved.