背景
闭包是python特有的语法功能,先看以下小例子。定义了函数func1(),并且打印了这个函数的名称以及类型,然后正常调用了这个函数,因此在出现了打印的一行结果。
然后使用变量x指向了func1,即x现在是func1的一个引用(这一点类似与变量的赋值操作),因此打印x以及type(x)会得到先前一样的结果,并且可以像调用func1一样调用x这个函数。
def func1():
print('this is func1')
if __name__ == '__main__':
print('闭包测试')
print(type(func1))
print(func1)
func1()
print('==================')
x = func1
print(type(x))
print(x)
x()
结果:
<class 'function'>
<function func1 at 0x00818D68>
this is func1
==================
<class 'function'>
<function func1 at 0x00818D68>
this is func1
闭包的原理基本与上面的例子相同,但是还有一些其他的要求。
- 函数中定义另一个函数,
- 在内侧的函数用到了外侧函数的临时变量
- 在外函数的返回值是内函数的引用
def func(num):
print('in func')
def func_inner():
print('in func_inner')
print(num)
return func_inner
if __name__ == '__main__':
func(10)
print('*' * 10)
x = func(10)
print(type(x))
print(x)
x()
结果:
in func
**********
in func
<class 'function'>
<function func.<locals>.func_inner at 0x018A8DF8>
in func_inner
10
来一行一行分析吧。函数func有一个参数,并且有返回值(返回值是内侧函数的引用)。只不过在这个函数内部还定义了一个函数func_inner(),这个函数是否需要返回值根据实际的需求,但是这个内侧的函数用了外侧函数的一个临时变量num。在执行了函数func(10)之后发现内侧函数中的打印并没有直接打出来。
用变量x接受func(10)的返回值后发现x指向的是刚刚调用func(10)时内侧的func_inner(),由第一个例子可知返回值x可以再次被调用,因此出现了最后的这个结果。
闭包的实际应用主要是装饰器,这也是一个很重要的知识点。