闭包行为(python)

时间:2015-09-13 01:19:04

标签: python

我正在观看O'Reilly媒体的蟒蛇顿悟,他们以此为例

def log(severity,message):
    print("{0}:{1}".format(severity.upper(),message))

def create_logger(severity):
    def logger(message):
        log(severity,message)
    return logger

warning2 = create_logger("warning")
warning2("this is a warning")

输出:

WARNING:this is a warning

我对装饰器有点了解,create_logger的格式与装饰器完全相同,只是它没有被用作装饰器。

令我难以置信的是 这一行warning2("this is a warning")

warning2包含create_logger函数,参数为"warning" 所以它基本上已经被调用了

并且warning2("this is a warning")就像打电话两次一样?

但我确实注意到:

create_logger("warning")("this is a warning")

产生相同的结果 这会让我相信第二个电话,("this is a warning") 隐式引用logger中的create_logger函数并将参数传递给它?

我理解对吗? 什么时候我们需要使用它?

2 个答案:

答案 0 :(得分:1)

Array ( [Random Header 1] => Array ( [0] => 1. List item 1 [1] => 2. List item 2 [2] => 3. List item 3 ) [Random Header Title 2] => Array ( [0] => 1. List item 1 [1] => 2. List item 2 [2] => 3. List item 3 ) ) 是一个函数,其返回值是另一个函数。当您调用create_logger时,其中定义的函数create_logger不会被调用;它刚刚归还。因此,当您执行logger时,warning2 = create_logger('warning')是一个函数。 warning2然后正常调用它。第二个电话没有"隐含地"参考内部功能;第一个调用返回对内部函数的显式引用。

至于为什么要使用它,它可能非常强大。在其他函数中定义函数的能力允许您创建一种"骨架"内部函数可以提供某个任务的轮廓,然后您可以使用传递给外部函数的参数将其充实。在这种情况下,warning2("this is a warning")是"骨架"谁的肉体"是通过致电logger提供的。您提到的装饰器是嵌套函数最突出的用途之一。

答案 1 :(得分:1)

我要在闭包上借用Simeon Franklin中的一些单词(并且,通过扩展,装饰器):

  

Python支持一个名为 function closures 的功能,这意味着在非全局范围内定义的内部函数会记住它们在定义时间时的封闭名称空间。

所以是的,这是一个关闭。装饰者使用闭包,但你不必让装饰者使用闭包。

为此,让我们深入研究所说内容的第二部分:非全局空间中定义的内部函数会记住它在定义时的封闭命名空间。

在定义时,这就是它的样子。

def logger(message):
    log("warning",message)
return logger

由于我们将"warning"传递给外层的severity,因此其值必须与#34;警告"关闭内部。

此时,我们所做的只是定义一个参数为message的方法,我们通过warning2引用它。

然后我们通过warning2("this is a warning")调用此方法。

这也是currying operation有效的原因:create_logger("warning")("this is a warning")与上面的代码完全相同,但我们根本没有用{{1来跟踪函数的创建在任何地方绑定其严重性。

为什么这有用?这使您能够编写创建函数的函数,或者使您能够对大量代码进行重复数据删除。想象一下,如果您必须使用需要提供其严重性级别和消息的记录器,理想情况下,您需要提供的只是其消息,并且您将选择最适合该任务的记录器功能。这段特殊代码可以帮助您实现这一目标。