这个with_default_value
函数通常(不准确地)被称为“闭包”(从技术上讲,闭包是返回的内部函数,这里newfunc
- 参见例如这里)。更一般地说,with_default_value
是一个高阶函数(“HOF”):它接受一个函数 ( func
) 作为参数,它还返回一个函数 ( newfunc
) 作为结果。
我已经看到答案将其与 Python 中的装饰器概念和构造混淆了,这绝对不是这种情况——尤其是因为您经常提到func
它是内置的,例如int
. 装饰器也是高阶函数,但更具体的是:返回装饰的,即“丰富的”,其函数参数的版本(它必须是唯一的参数——“带参数的装饰器”是通过一个更高级别的函数/闭包嵌套,而不是给装饰器 HOF 多个参数),它被重新分配为与该函数参数完全相同的名称(因此通常具有相同的签名 - 否则使用装饰器将非常奇特的、不习惯的、不可读的等)。
所以忘记与案例完全无关的装饰器,并专注于newfunc
闭包。词法嵌套函数可以引用(尽管不能重新绑定)封闭函数的所有局部变量名称(包括参数名称,因为参数是局部变量)——这就是它被称为闭包的原因:它“封闭”这些“自由变量”。在这里,newfunc
可以参考func
and default
--does。
高阶函数在 Python 中是一件很自然的事情,特别是因为函数是一等对象(所以你不需要做任何特别的事情来将它们作为参数传递,将它们作为函数值返回,甚至将它们存储在列表或其他容器中等),并且函数和其他类型的对象之间没有命名空间的区别,没有仅仅因为提到它们就自动调用函数等等。(它更难 - 有点难,或者更难,取决于 - 在其他语言中确实吸引了很多这种区别)。在 Python 中,提及一个函数就是——提及;只有当函数对象(以名称或其他方式引用)后跟括号时,才会发生 CALL。
这就是这个例子的全部内容——如果您对其他一些具体方面仍有疑问,请随时编辑您的问题、在此处发表评论等!
编辑:所以 OP 礼貌地评论,要求提供更多“关闭工厂”的例子。这是一个 - 想象一些抽象的 GUI 工具包,你正在尝试做:
for i in range(len(buttons)):
buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))
但这不起作用——i
在lambda
后期绑定中,所以当一个按钮被点击i
的时候,它的值总是最后一个按钮的索引,无论哪个被点击。有多种可行的解决方案,但关闭工厂是一种优雅的可能性:
def makeOnclick(message):
return lambda: mainwin.settitle(message)
for i in range(len(buttons)):
buttons[i].onclick(makeOnClick("button %d click!" % i))
在这里,我们使用闭包工厂来调整变量的绑定时间!-) 在一种或另一种特定形式中,这是闭包工厂的一个非常常见的用例。