文章目录

  • 1. Python中的嵌套函数
  • 2. Python闭包
  • 3. 何时以及为何使用闭包
  • 参考文献


(翻译文,扩充了一些文字和代码便于理解)
    在了解闭包(closure)是什么之前,我们必须首先了解什么是嵌套函数和非局部变量。

1. Python中的嵌套函数

    在一个函数内部定义的函数称为嵌套函数。嵌套函数能够访问范围内的变量。
    在Python中,这些非局部变量只能在其作用域内访问,而不能在其作用域外访问。可以通过以下示例进行说明:
示例一

# Python program to illustrate 
# nested functions 
def outerFunction(text): 
    text = text 
  
    def innerFunction(): 
        print(text) 
  
    innerFunction() 
  
if __name__ == '__main__': 
    outerFunction('Hey!')

    如我们所见, innerFunction() 可以很容易地访问outerFunction函数内部的属性,但不能访问outerFunction函数外部。在这里, innerFunction() 是嵌套函数,该函数使用 text,text为非局部变量。如果需要使用非局部变量,嵌套函数的外层函数必须先定义变量。内层函数使用nonlocal关键字声明该变量为非局部变量,使内层函数能够修改外层函数定义的变量;如果不使用nonlocal关键字,内层函数无法改变外层函数的变量值。关于非局部变量,这有一篇文章写得很好,点击浏览 PS:
    题外话,简单用C语言实现了一下上面代码,python确实是简单,代码量确实是少一些的,但是python需要一定的抽象思维。

#include <stdio.h>

void outerFunction(char * text)
{
    char * ptr;
    ptr = text;

    void interFunction(char * ptr)
    {
        int i;
        for(i=0;ptr[i] != '\0';i++)
        {   
            printf("%c", ptr[i]);
        }
        printf("\n");
    }

    interFunction(ptr);
}

int main(void)
{
    char a[]="Hey!";
    outerFunction(a);
}
2. Python闭包

    闭包是一个函数对象,它会记住封闭作用域(即嵌套函数)中的值,即使它们不在内存中。
示例二

# Python program to illustrate 
# closures 
def outerFunction(text): 
    text = text 
  
    def innerFunction(): 
        print(text) 
  
    return innerFunction # Note we are returning function WITHOUT parenthesis 
  
if __name__ == '__main__': 
    myFunction = outerFunction('Hey!') 
    myFunction()

    输出:

# python3 Closures.py 
Hey!

    与示例一相比,示例二不同寻常的地方在于outerFunction函数执行完毕,返回的是函数,并且,该返回函数绑定到了myFunction名下。调用myFunction函数时,outerFunction函数早就执行完毕了,但所有信息依然存在。
    1、从上面的代码可以看出,闭包有助于在其作用域之外调用函数。
    2、innerFunction函数在outerFunction函数中有其自己的作用域。但是,通过使用闭包,我们可以轻松扩展其作用域,以调用其作用域之外的函数。
示例三

# Python program to illustrate 
# closures 
import logging 
logging.basicConfig(filename='example.log', level=logging.INFO) 
  
  
def logger(func): 
    def log_func(*args): 
        logging.info( 
            'Running "{}" with arguments {}'.format(func.__name__, args)) 
        print(func(*args)) 
    # Necessary for closure to work (returning WITHOUT parenthesis) 
    return log_func               
  
def add(x, y): 
    return x+y 
  
def sub(x, y): 
    return x-y 
  
add_logger = logger(add) 
sub_logger = logger(sub) 
  
add_logger(3, 3) 
add_logger(4, 5) 
  
sub_logger(10, 5) 
sub_logger(20, 10)

    执行结果:

# python3 MoreOnClosures.py  
6
9
5
10

PS:
    题外话,上面这个示例,也可以使用装饰器实现,Python装饰器大量使用了闭包,代码如下

# Python program to illustrate 
# closures 
import logging
logging.basicConfig(filename='example.log', level=logging.INFO)


def logger(func):
    def log_func(*args):
        logging.info(
            'Running "{}" with arguments {}'.format(func.__name__, args))
        print(func(*args))
    # Necessary for closure to work (returning WITHOUT parenthesis) 
    return log_func

@logger
def add(x, y):
    return x+y

@logger
def sub(x, y):
    return x-y

add(3, 3)
add(4, 5)

sub(10, 5)
sub(20, 10)
3. 何时以及为何使用闭包

    在Python中创建闭包必须满足的条件:

  • 必须有嵌套函数
  • 嵌套函数必须引用封闭函数中定义的值
  • 封闭函数必须返回嵌套函数

    闭包的作用:
    1.由于闭包用作回调函数,因此它们提供了某种数据隐藏。这有助于我们减少使用全局变量。
    2.当我们的代码中没有几个函数时,闭包被证明是一种有效的方法。但是如果我们需要很多功能,那就需要使用类(OOP)。