python 装饰器
2020-04-01 本文已影响0人
周周周__
装饰器是一种面向切片的思想。主要用到的地方就是给函数封装一个方法。我个人用到的地方就是封装日志。
装饰器是函数的闭包:
简单的理解就是在函数中执行函数
1、为了给函数添加新的功能,普通实现。
def A():
pring("a")
def B():
return "b"
b = B()
return b
A()
在上边的两个函数中, 当我们有一个原始函数B,我们想给B封装一个新的功能,比如这个功能就是在执行B的时候打印一下a,上边的这个函数完全实现了这样的方法,但是这样看来是很不优雅的。对于我们多个需要这个功能的函数是不友好的。所以我们有了装饰器。
2、装饰器实现
def check_rank(func):
def wrapped_function(*args, **kwargs):
print('我是装饰器方法。。')
return func(*args, **kwargs)
return wrapped_function
@check_rank
def A(x):
print('123', x)
A(a)
执行A(1), 结果:
结果.png
其中,
*args, **kwargs是用来接收参数的。这个方法很好理解,将A函数作为参数传给chenk_renk,在里面封装好的函数wrapped_function里面接收参数,并执行A函数。这个里面就是把需要的功能封装成函数
wrapped_function,在函数中,首先执行了自己的功能,然后返回的是执行需要执行的函数A,并将执行结果进行返回。把这个结果传到外边函数,外边的函数再将wrapped_function的结果进行返回。
其中,我们针对不通的函数,可能有不同的参数需要传递,比如,flask中的路由,我们传递不同的参数,来给函数绑定不同的路由。这个时候我们就得考虑装饰器传参。
3、装饰器传参
我们都知道,flask值将所有的url都放在了urlmap里面,我们这里可以模仿flask的路由匹配(很牵强,不要在意)。将注册过的路由放在了url_map里面。在装饰器中,只有匹配到了路由才能正常执行。
函数的整个过程只是外边又包装了一个闭包,把装饰器的值进行接收。
from functools import wraps # 这个是一个基本的方法,为了保证我们装饰器还能打印出当前函数的名称,而不是打印出装饰器函数的名称
url_map = ['/app']
def url_re(res):
def url_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
if res in url_map:
a = func(*args, **kwargs)
else:
a = "you are wrong"
return a
return wrapped_function
return url_decorator
@url_re('/app')
def N():
print("我是函数N")
return 'sucess'
@url_re('1')
def M():
print("我是函数M")
return
n = N()
print(n)
m = M()
print(m)
结果:
结果.png
4、使用场景说明
1、后端接口鉴权
源码举例:这是针对不同用户权限进行限定访问的
def check_rank(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
if current_user.rank == 2:
return redirect_back('/')
elif current_user.rank == 1:
return func(*args, **kwargs)
return wrapped_function
2、日志实现(伪代码)
def log_db(request):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
a = func(*args, **kwargs)
try:
id = requests.remote_addr
time = time.time()
msg = requests.mag
with open('./logs.log', 'a') as f: # 多进程部署加锁
f.write(time + id + msg)
except Exception as e:
print(e)
return a
return wrapped_function
return logging_decorator