是否可以为已经定义的函数定义一个闭包?
例如,我想要一个“原始”函数和一个已经由周围的闭包设置一些预定义值的函数。
这是一些代码,显示了我可以使用闭包将预定义变量添加到函数定义中的操作:
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
,但无法使其正常工作。
但这有可能吗?如果是的话:是否有任何模块已经为此实现了装饰器?
答案 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
并通过它传递额外的变量。否则,我对仅在包装后才能使用的“内部功能”构造不熟悉。