闭包的理解基础
闭包解决的是函数嵌套的变量访问问题
非闭包场景
内部函数 inner_fun 可以成功访问外部变量 x
1 | def outer_fun(x): |
6
如果在内部函数 inner_fun 要修改变量 x 的值,就行不通了
1 | def outer_fun(x): |
x += 1
UnboundLocalError: local variable ‘x’ referenced before assignment
这时想修改必须 在内部函数 inner_fun 中声明 nonlocal 变量才行
1 | def outer_fun(x): |
7
闭包场景
闭包举例
这里将外部函数 outer_fun 的返回,return 为这个嵌套函数 inner_fun
outer_fun(6) 调用了第一次后,x + 1 = 7
再次调用 outer() 时,记住了这个变量 7
1 | def outer_fun(x): |
7
注意看 outer = outer_fun(6) 这一行代码,是不是跟类的实例化非常相似呢?
这就是闭包,可以将一些变量数据直接附加到“闭包”里面,
此时这个“闭包”会记住这些变量数据。
好比面向对象的封装一样,把一些属性和变量封装到一个对象类里面
怎么创建一个闭包
首先它得是一个嵌套函数
接着内部函数引用nonlocal变量
最后嵌套函数的返回是内部函数
闭包具体应用简单举例
1 | def outer_fun(x): |
TypeError: inner_fun() missing 1 required positional argument: ‘y’
这里会报错,因为内部函数 inner_fun 也要传入一个参数 y
1 | def outer_fun(x): |
6
11
65
outer = outer_fun(5) 引用记住了参数 5
outer(1) outer(6) outer(60) 依次执行 + y 的操作
可以看到,当我们使用闭包的时候,
我们不需要定义全局变量,也可以访问到函数内部的数据
(一般情况下函数外部是没有办法访问函数内部的变量数据的),
也就是说可以拿到闭包提供的隐藏数据。
注意看 outer = outer_fun(5) 这一行代码,是不是跟类的实例化非常相似呢?
这样的话,如果我们的某个功能只需要一个函数的话,那么我们就直接写一个闭包,而不用写一个类那么麻烦。
我想,往后我跟你说装饰器的时候,你会更加明白闭包的应用。
总之,Python 中的闭包就像一个包,
这个包的牛逼之处在于,
它可以让我们引用函数中的 nonlocal 变量,
这个包可以隐藏一些变量数据,当我们需要的时候,就可以从这个包获取。
当你发现你要写的类只需要一个方法就能实现的时候,用闭包是一种更好的选择。