文章目录
- 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)。