12. 闭包
一、闭包
在一个函数内部,我们可以在在定义一个函数,并且将内部的函数作为外部函数的返回值返回。这种高阶函数,我们也称为 闭包。“闭” 是指该函数是内嵌函数,“包” 是指该函数包含外层函数作用域的引用(不是对全局作用域)。通过闭包,我们可以创建一些只有当前函数能访问的变量,我们可以将一些私有的数据藏在闭包中。
形成闭包的要件:① 函数嵌套;② 将内部函数作为返回值返回;③内部函数必须要使用外部函数的变量;
正常来说,调用一个函数的时候,这个函数中的所有局部变量+形参都只会在这个函数执行过程中才会保留,只要这个函数执行完毕,那么这些局部变量+形参就会被自动释放,也就说没有了。闭包比普通的函数强大的地方在于,它在外部函数执行完毕之后,这个外部函数中的所有局部变量+形参,都不会被释放,以便在于调用内部函数的时候可以使用。
闭包的好处可以将局部变量永久存储,但是多占用内存;由于闭包会携带包含它的函数的作用域,因此会比其它函数占用更多的内存。因此,可以手动解除会匿名函数的引用,以便释放内存;
def outer(count=0):
# 在函数内部再定义一个函数
def inner():
print("我是内部函数")
# 内层函数修改外层函数的数据
nonlocal count
count += 1
# 内层函数访问外层函数的数据
print(count)
return inner
fun = outer()
fun()
fun()
fun()
fun 是一个函数,它是调用 outer() 后返回的函数。这个函数是在 outer() 内部定义的,并不是全局函数,所以这个函数总是能访问到 fun() 函数内的变量。在闭包中的内部函数中,如果没有用 nonlocal 关键字来声明外部函数的变量,则不能对其进行修改,只能进行访问;
二、闭包的应用
通过闭包我们可以在没有改变原函数的前提下,拓展功能。
def add(a,b):
return a+b
def say_hello():
print("hello world!")
def outer(func):
"""
用来对其它函数进行扩展,使其函数可以在执行前打印开始执行,执行后打印执行结束
@param inner 要扩展的函数
@return inner 返回扩展函数
"""
# 创建一个新函数
def inner(*args, **kw_args):
# 在原函数执行前扩展功能
print("开始执行!")
# 调用被扩展的函数
result = func(*args, **kw_args)
# 在原函数执行后拓展功能
print("执行结束!")
# 返回函数执行结果
return result
# 返回新函数
return inner
# 将原函数名指向的内存地址偷梁换柱成装饰器内部新创建函数(inner())的内存地址
add = outer(add)
result = add(10,20)
print(result,'\n')
say_hello = outer(say_hello)
say_hello()