Python 闭包与函数属性
我尝试重新实现一个类似于 partial
的东西(以后会有更多的功能)。在下面的例子中,lazycall1
看起来和 lazycall2
一样好用,所以我不明白为什么 关于 partial
的文档 建议使用更长的第二种写法。有什么建议吗?这样做会有什么问题吗?
def lazycall1(func, *args, **kwargs):
def f():
func(*args, **kwargs)
return f
def lazycall2(func, *args, **kwargs):
def f():
func(*args, **kwargs)
f.func=func # why do I need that?
f.args=args
f.kwargs=kwargs
return f
def A(x):
print("A", x)
def B(x):
print("B", x)
a1=lazycall1(A, 1)
b1=lazycall1(B, 2)
a1()
b1()
a2=lazycall2(A, 3)
b2=lazycall2(B, 4)
a2()
b2()
补充:其实到目前为止给出的答案并不完全正确。即使是双重参数也能正常工作。还有其他原因吗?
def lazycall(func, *args):
def f(*args2):
return func(*(args+args2))
return f
def sum_up(a, b):
return a+b
plusone=lazycall(sum_up, 1)
plustwo=lazycall(sum_up, 2)
print(plusone(6)) #7
print(plustwo(9)) #11
3 个回答
0
functools.partial 可以在返回的内部函数中接受额外的参数,或者覆盖一些参数。而你内部的 f()
函数并不需要这些,所以在 lazycall2
中你做的事情其实没必要。不过,如果你想做类似的事情:
def sum(a, b):
return a+b
plusone = lazycall3(sum, 1)
plusone(6) # 7
那么你就需要按照文档中展示的那样去做。
0
仔细看看你提到的Python文档中,内部函数newfunc
的参数名称,它们和传给这个内部函数的参数名称是不同的,比如args
和fargs
,还有keywords
和fkeywords
。他们实现的partial
功能是保存外部函数传入的参数,并把这些参数加到内部函数接收到的参数中。
因为你在内部函数中使用了完全相同的参数名称,所以外部函数传入的原始参数在内部函数里是无法访问的。
至于在外部函数上设置func
、args
和kwargs
属性,Python中的函数其实也是一种对象,你可以在它上面设置属性。这些属性让你在把它们传入lazycall
函数后,仍然能访问到原始的函数和参数。所以a1.func
会是A
,而a1.args
会是[1]
。
如果你不需要跟踪原始的函数和参数,那么使用你的lazycall1
就没问题。
2
第二种形式唯一多出来的就是一些额外的属性。如果你开始传递lazycall2返回的函数,这些属性可能会很有用,因为接收这些函数的地方可以根据这些属性的值做出一些决定。