上一篇文章我介绍了python的变量作用域和LEGB规则。今天接着介绍python中函数的闭包和nonlocal语句
1、闭包的概念: 闭包(closure)是函数式编程的重要的语法结构。如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是 closure。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。closures 在函数式编程中是一个重要的概念。 简单闭包例如:我们会模拟一个计数器代码如下
其中,count就是LEGB中的E(Enclosing function locals)具体LEGB参考上一篇文章 上面的代码就是简单的闭包操作,counter()做的事就是接受一个初始化的的值来开始计数,并将该值赋给列表 count。然后定义一个 incr()的内部函数。通过在内部使用变量 count,我们创建了一个闭包,因为它现在携带了整个 counter()作用域。incr()增加了正在运行的 count 然后返回它。然后最后的就是 counter()返回一个incr,一个(可调用的)函数对象。这个和类的实例化很像,但是这个比类要简单。 两个参数闭包实例,上面的闭包是最简单的闭包,下面这个为内嵌函数也需要参数,来看一下:
上图中,有两个参数,当我们第一次调用outer初始化给tes的时候,传入的参数为x 在我们利用tes调用内嵌函数时候,再次传入的参数为内函数的参数。 注意:使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量。所以我们看到第二次输出的结果为10。两次引用的闭包变量为同一个。 ![]()
为什么你会想要用 closues? 1、 装饰器。函数装饰器就是在闭包的基础上多了几步。等下次我再介绍装饰器。 2、Closurs 对于安装计算,隐藏状态,以及在函数对象和作用域中随意地切换是很有用的。 3、closurs在 GUI 或者在很多 API 支持回调函数的事件驱动编程中是很有些用处的。 4、'惰性求值',以绝对相同的方式,应用于获取数据库行和处理数据。 5、并行运算。闭包有效的减少了函数所需定义的参数数目。这对于并行运算来说有重要的意义。
2、Nonlocal语句 前面讲了闭包,那我们在内嵌函数中如何修改闭包中的变量呢?这时候就到了nonlocal出场了。 Python3 中引进了nonlocal语句,它和global语句差不多,不过就是global语句是应用于全局模块作用域,nonlocal 应用于嵌套函数内作用域中的一个名称。在声明nonlocal名称的时候,它必须存在于该嵌套函数的作用域中,并且不能由def中的第一次赋值创建。 ![]()
Nonlocal允许内嵌的函数来修改闭包变量。 形式如下: 实例:
我们可以发现,当我们第一次调用outer的时候,init被赋值为5,然后再内嵌函数中我们使用nonlocal语句,修改了init。 码字不易,多多关照。不足之处,欢迎指正。 |
|
来自: flyk0tcfb46p9f > 《AI》