在了解装饰器之前, 我们需要知道什么闭包是什么鬼!
闭包: 在一个函数内定义了一个函数 f, 并且这个函数 f 引用外部变量, 在把这个函数 f 当做返回值返回.
上述说了闭包的三个条件:
1 函数内定义了一个函数 f
2 f 函数引用了外部变量
3 f 被当做返回值返回
- def t1():# 定义 t1 函数
- x=2
- def f():#t1 函数内部定义了 f 函数
- print(x)#f 函数引用了不属于自己内部的变量 x
- return f #f 被当做返回值返回
而装饰器有是什么鬼呢? 其实闭包的一种运用.
装饰器: 在不改变函数 (当然还有其他的) 的代码和调用方式的前提下, 为函数增加新的功能!
那么需求来了: 例如我定义了一个下载方法, 我在想不改变下载方法的代码和调用方式, 为其加一个需要登录后才能下载的功能
- def get(file):# 下载方法
- print('下载成功',file)
那么如何实现呢? 这里就要用到上面提到的闭包.
我们再来看看闭包, 即是在一个函数内定义了一个函数 f, 并且这个函数 f 引用外部变量, 在把这个函数 f 当做返回值返回
那么上面的需求我们可以先试着做第一步, 即是不改变下载方法的代码, 为其加一个需要登录后才能下载的功能
- def get(file):# 下载方法
- print('下载成功',file)
- def auth(get,*args,**kwargs):
- print('登录方法')
- get(*args,**kwargs)
- auth(get,'a.txt')
- # 结果:
- # 登录方法
- # 下载成功 a.txt
但是这样的话调用方式改变了, 那么我们可以利用闭包:
- def get(file):# 下载方法
- print('下载成功',file)
- def func(get):
- def auth():
- print('登录方法')
- get()
- return auth
- get=func(get)
- get('dasd')
这样的话, 参数有传不进去, 并且报错参数没有接收到:
我们分析一下上面代码 func(get)其实应该是 auth 这函数名, 那么 get=func(get), 就是把 auth 赋值给 get 变量, 即是次数 get=auth,
那么 我们调用 get('dasd') 即是 auth('dasd'), 即是我们需要修改 auth 函数
- def get(file):# 下载方法
- print('下载成功',file)
- def func(get):
- def auth(file):
- print('登录方法')
- get(file)
- return auth
- get=func(get)
- get('dasd')
这样的话 get('dasd')的时候就是调用 auth('dasd'), 那么会执行登录方法, 并且执行 get('dasd'), 这里是真正的下载方法
优化一下就是这样的:
- def auth(f):
- def wrapper(*args,**kwargs):
- print('其它功能或方法')
- f(*args,**kwargs)
- return wrapper
这样的要装饰 get 函数的时候, 只需 get=auth(get), 这里第一个 get 是变量, 第二个 get 是函数名, 这样就实现 get 不改变其的代码和调用方式, 为其增加功能.
在 python 中 get=auth(get), 可以省略为:
- def auth(f):
- def wrapper(*args,**kwargs):
- print('登录方法')
- f(*args,**kwargs)
- return wrapper
- @auth # 相当于 get=auth(get)
- def get(file):# 下载方法
- print('下载成功',file)
当然上面是装饰器的无参装饰器, 还有有参装饰器:
- # 有参装饰器
- def authx(a):
- def auth(f):
- def wrapper(*args, **kwargs):
- if a=='a':
- print('登录方法')
- else:
- print('adad')
- f(*args, **kwargs)
- return wrapper
- return auth
- @authx('adas') # 相当于 get=auth(get) 当然 a 的值也传入了
- def get(file):# 下载方法
- print('下载成功',file)
来源: https://www.cnblogs.com/wh-alan/p/9287434.html