闭包函数和装饰器
闭包函数
闭就是封闭(函数内部的函数),包是包含(在内部函数外面包了一层局部作用域,使得对于他而言的外部的作用域不再是全局作用域,而是外层包裹的函数对应的局部作用域)
给函数传参的两种方式
- 使用参数
def func(x):
print(x)
func(1) # 1
- 包给函数(利用函数名可以当做参数传给一个函数和函数名可以当做另一个函数的返回值)
def outter(x):
def func():
print(x)
return func
f=outter(1) # 调用outter的时候内部没有可执行的代码,返回一个函数名func,把这个函数名赋值给f,同时在这个outter函数对应的局部名称空间中有一个x=1
f() # 调用f()实质上是在调用func(),程序调用func()函数,执行内部print命令,然后从func对应的局部名称空间找x,然后再从外层包裹的outter函数对应的局部名称空间查找x,找到x=1,打印
闭包函数的应用
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用.优先使用自己外层包裹的函数对应的作用域
装饰器
器是指工具,而程序中的函数就是具备某一种功能的工具,所以装饰器指的是为被装饰对象添加额外的功能,因此定义装饰器就是定义一个函数,只不过该函数的功能是用来给其他函数添加额外的功能,装饰器本身可以是任意可调用对象,被装饰的对象也可以是任意可调用的对象.
为什么要用装饰器
装饰器可以在不修改被装饰对象的源代码,以及不修改被装饰对象的调用方式的情况下为被装饰对象添加新功能
如何使用装饰器
# deco就是装饰器
def deco(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
def sleep():
print('zaoshanghao')
sleep=deco(sleep)
sleep()
- 调用装饰器并把sleep当做参数传入
- 装饰器内部只有定义函数和一个返回函数,所以调用函数的时候不会执行wrapper函数,仅返回wrapper这个名字
- 利用函数对象的概念将装饰器赋值给原函数名,相当于将wrapper这个名字赋值给原函数名
- 原函数名+()执行的时候相当于调用装饰器内部的wrapper函数
- wrapper函数的可变长形参会接收外层装饰器传入的所有参数,并赋值给内层的函数,如果传入一个原函数的名字,则可以在,最里层直接调用原函数
- 最内层的函数是直接调用的而不是定义,所以代码直接运行
- wrapper函数内可以按需求增加功能,如果原函数有返回值的话,wrapper函数也应该有返回值,所以我们可以将最内层的函数赋值给res,在wrapper中returnres达到和原函数一样的效果
- 如果原函数需要传参,由于wrapper相当于原函数,所以我们只要给wrapper函数传参就行,并且由于不确定具体的需要传入的实参且装饰器是可以是一个通用的模板,所以我们使用可变长实参\形参 args和*kwarg作为wrapper的形参以及最内层func函数的形参来接收所有传入的参数
装饰器语法糖
在被装饰对象正上方单独写一行 @装饰器名,可以节省一行代码
原函数名=装饰器名(原函数名)