from functools import partial
i = 0
f0 = partial(callback, i)
i = 1
f1 = partial(callback, i)
f0()
f1()
partial
类似于lambda表达式,但它会将该时刻的值包装到参数中,而不是在调用时计算。
仅包装部分参数
是的,partial可以让你包装任意数量的参数,剩余的args和kwargs可以传递给生成的partial对象,使其像调用原始包装函数一样运行...
def callback(val1, val2):
print "{0} {1}".format(val1, val2)
i = 0
x = 8
f0 = partial(callback, i)
f0(x)
本质上,您已经将 callback(val1, val2)
包装成了 callback(val2)
,其中 val1
已作为闭包被包含在内。
使用lambda实现类似效果的示例
如果您真的想看看如何使用lambda闭包来完成这个过程,您会发现它变得很丑陋,而部分应用则更受欢迎...
f0 = (lambda val1: lambda val2: callback(val1, val2))(i)
你需要将作用域变量包装在外部函数作用域中,然后在内部lambda函数中引用该作用域。但是这样做比较麻烦。
异常的追踪:partial vs lambda vs nested functions
随着其他答案的涌现,我想再提出一个使用partial而不是lambda或内/外函数闭包的原因。请记住,我指的是函数闭包。 functools.partial可以修复当包装函数引发异常时,您将得到的回溯信息...
考虑此版本,它将引发除零错误:
def callback(val1, val2):
return val1 / val2
常规外部/内部闭包
def wrapper(fn, val1):
def wrapped(val2):
return fn(val1, val2)
return wrapped
f0 = wrapper(callback, i)
f0(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in wrapped
File "<stdin>", line 2, in callback
ZeroDivisionError: integer division or modulo by zero
lambda闭包
f0 = (lambda val1: lambda val2: callback(val1, val2))(i)
f0(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 2, in callback
ZeroDivisionError: integer division or modulo by zero
现在来谈 functools.partial
f0 = partial(callback, i)
f0(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in callback
ZeroDivisionError: integer division or modulo by zero
i
。 - jdipartial
。 - Joel Cornett