函数定义后关闭

时间:2018-08-10 18:16:09

标签: python closures

是否可以为已经定义的函数定义一个闭包? 例如,我想要一个“原始”函数和一个已经由周围的闭包设置一些预定义值的函数。
这是一些代码,显示了我可以使用闭包将预定义变量添加到函数定义中的操作:

def outer(a, b, c):
    def fun(d):
        print(a + b + c - d)
    return fun

foo = outer(4, 5, 6)
foo(10)

现在,我想在包装闭包函数之外定义fun,以便能够使用闭包中的变量或直接传递变量来调用fun。我知道我需要重新定义一个函数以使其在闭包中可用,因此我尝试为其使用lambda

def fun(a, b, c, d):  # raw function
    print(a + b + c - d)

def clsr(func):  # make a "closure" decorator
    def wrap(*args):
        return lambda *args: func(*args)
    return wrap

foo = clsr(fun)(5, 6, 7)  # make a closure with values already defined
foo(10)  # raises TypeError: fun() missing 3 required positional arguments: 'a', 'b', and 'c'
fun(5, 6, 7, 10)  # prints 8

我还尝试过使用wraps中的functools,但无法使其正常工作。

但这有可能吗?如果是的话:是否有任何模块已经为此实现了装饰器?

1 个答案:

答案 0 :(得分:2)

您可以随时定义包装:

def fun(a, b, c, d):  # raw function
    print(a + b + c - d)

def closed(d): fun(5,6,7,d)

closed(10)

您可以将其与lambda一起使用,但是@juanpa指出如果没有理由,则不应该这样做。上面的代码将得到8。顺便说一句,该方法不是特定于Python的,大多数语言都支持此方法。

但是如果,您需要某种意义上的关闭,那就是它依赖于包装变量,而不是,并且有充分的理由不这样做。这实际上将创建一个依赖包装的非工作功能。在这种情况下,使用类可能更好:

class fun:
    def __init__(self,*args): #Can use specific things, not just *args.
        self.args = args #Or meaningful names
    def __call__(self,a, b, c, d): # raw function
        print(a + b + c - d,self.args)

def closed(d): 
    fun("some",3,"more",['args'])(5,6,7,d)

closed(10)

或直接使用*args/**kwargs并通过它传递额外的变量。否则,我对仅在包装后才能使用的“内部功能”构造不熟悉。

相关问题