一:闭包
1、定义:
闭包是函数式编程的一个重要的语法结构,函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式)。在面向过程编程中,我们见到过函数(function);在面向对象编程中,我们见过对象(object)。函数和对象的根本目的是以某种逻辑方式组织代码,并提高代码的可重复使用性(reusability)。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
不同编程语言实现闭包的方式是不同的,python中闭包从表现形式上看,如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
举个例子:
def outer(x):
def inner(y):
return x + y
return inner
结合这段简单的代码和定义来说明闭包:
inner(y)就是这个内部函数,对在外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量,x在外部作用域outer里面,但不在全局作用域里,则这个内部函数inner就是一个闭包。
再稍微讲究一点的解释是,闭包=函数块+定义函数时的环境,inner就是函数块,x就是环境,当然这个环境可以有很多,不止一个简单的x。
在函数outer中定义了一个inner函数,inner函数访问外部函数outer的(参数)变量,并且把inner函数作为返回值返回给outer函数。
a = outer(2)
print('function:',a)
print('result:',a(3))
上面的代码中a就是一个函数,代码的执行结果为:
从结果我们不难看出,a是函数inner而不是outer,这个有点绕,但是并不难理解,因为return回来的是inner函数
2、使用闭包注意的地方:
①闭包无法修改外部函数的局部变量
通过上面的程序我们发现:虽然在innerFunc函数中对变量 x 进行了修改,但是outerFunc函数中的变量 x 并没有发生变化
同样,引用类型数据也无法修改
②闭包无法直接访问外部函数的局部变量
运行报错:局部变量在声明之前引用,innerFunc函数不能访问到外部的局部变量
解决方法一:间接通过容器类型(字典、列表、元组、集合)来解决,因为容器类型不是存放在栈空间的,inner函数可以访问到
解决方法二:通过nonlocal关键字来解决,该语句显式的指定a不是闭包的局部变量
③在程序里面经常会出现循环语句,Python的问题就在于,当循环结束以后,循环体中的临时变量不会销毁,而是继续存在于执行环境中。还有一个python的现象是,python的函数只有在执行时,才会去找函数体里的变量的值,在使用闭包时需要注意
二:装饰器
1、python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能
通过上面的案例,我们可以发现:当python解释器运行到第13行时,即装饰器装饰一个函数的时候,装饰器就已经自动被调用了,而不是等到被调用的时候才进行装饰,而在第19行,调用内置函数的时候,调用的是内置函数的函数体
2、装饰器装饰带有参数的函数
也可以使用可变参数*args和关键字参数*kwargs
3、装饰器对带有返回值的函数的装饰
函数即带有参数又带有返回值
4、带有参数的装饰器:若装饰器带有参数,可以在函数外面再嵌套一个函数解决,装饰器带有参数,它可以实现装饰不同的函数,返回不同的功能