文章目录
- 1. 认识闭包
- 2. 闭包简介
- 3. 闭包作用
- 4. 使用场景
- 5. 总结
1. 认识闭包
在真正学习闭包之前,我们可以先看下面这段代码:
money = 1000
def buy(num):
global money
money -= num
print("花费{},还剩{}".format(num, money))
buy(300)
buy(300)
buy(200)
通过变量money
记录总金额,函数buy
来消费,把变量money
设置成全局变量的方式来实现对变量money
值的修改。虽然功能实现了,但是存在两个问题:
- 代码不够整洁
- 全局变量被修改
针对这两个存在的问题,我们可以通过闭包来实现:
def buy(money):
def fun(num):
nonlocal money
money -= num
print("花费{},还剩{}".format(num, money))
return fun
fn = buy(1000)
fn(300)
fn(300)
fn(200)
2. 闭包简介
维基百科定义:在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。
简单来说,在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
注意:如果不修改外部函数的变量,只是引用,可以不用关键字nonlocal
修饰变量
3. 闭包作用
通过上面的例子,我们可以看出闭包有如下作用:
- 使用闭包不需要定义全局变量就可以实现通过函数,持续的访问,
- 局部变量无法共享和长久的保存,而全局变量可能造成变量污染,闭包既可以长久的保存变量又不会造成全局污染。
- 将外层函数的变量持久地保存在内存中,不会在外层函数调用后被自动清除。由于外层函数的变量在内存中被保存,因此会增加内存消耗,所以不能滥用闭包,否则会造成程序的性能问题,可能导致内存泄露。所以在退出函数之前,将不使用的局部变量全部删除。
4. 使用场景
闭包的作用我们都可以通过python中的类
来实现,那么闭包存在的意义在哪里呢?
- 装饰器:python中的装饰器可以通过闭包来实现
- 如果我们的对象中只有一个方法时,使用闭包比使用类更加简单和优雅(类似python中
lambda匿名函数
和方法)
5. 总结
- 闭包函数: 定义双层嵌套函数, 内层函数可以访问外层函数的变量将内存函数作为外层函数的返回,此内层函数就是闭包函数
- 闭包函数不定义全局变量,也可以让函数持续访问和修改一个外部变量
- 闭包函数引用的外部变量,是外层函数的内部变量。作用域封闭难以被误操作修改
- 使用闭包函数会占用额外的内存
- 使用闭包函数,想要修改外部函数的变量值,需要用
nonlocal关键字
声明这个外部变量