代码之家  ›  专栏  ›  技术社区  ›  JE_Muc

函数定义后的闭包

  •  0
  • JE_Muc  · 技术社区  · 6 年前

    是否可以为已定义的函数定义闭包? 例如,我希望有一个“raw”函数和一个已经由周围闭包设置了一些预定义值的函数。
    下面是一些代码,显示了如何使用闭包将预定义变量添加到函数定义中:

    def outer(a, b, c):
        def fun(d):
            print(a + b + c - d)
        return fun
    
    foo = outer(4, 5, 6)
    foo(10)
    

    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 ,但我没能成功。

    但这有可能吗?如果是:是否有任何模块已经为此实现了decorators?

    1 回复  |  直到 6 年前
        1
  •  2
  •   kabanus    6 年前

    您可以定义动态包装:

    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