一、什么是装饰器
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
二、以下是一个时间模块插入日志的装饰器
import functools
import time
def add_logs(func):
'''
1.创建装饰器,创建add_log装饰器, 被装饰的函数打印日志信息;
2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返
:paramfunc:
:return:
'''
def wrapper(*args,**kw):
start_time = time.time()
res = func(*args,**kw)
end_time = time.time()
print ('函数名:{0} 运行时间:{1}'.format(func.__name__ , (end_time - start_time)))
return res
return wrapper
@add_logs
def add(x,y):
time.sleep(1)
return x+y
a = add(1,20)
print(a)
从上面的例子中可以可以看出:装饰器就是一个闭包,闭包的定义:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包。
三、介绍一个用户权限模块的装饰器案例:
# Create an account
user_auth = [{'username':'lufei','password':'123456'}]
# # 初始登录状态信息
# current_dic = {'username': None, 'login': False}
# Initial login status information
login_dic = {'username':None, 'login':False}
# Create login function decorator
def auth_func(func):
def wrapper(*args,**kwargs):
if login_dic['username']and login_dic['login']:
res = func(*args, **kwargs)
return res
while True:
username =input('plase input username:')
password =input('plase input password:')
for user_dicin user_auth:
if username == user_dic['username']and password == user_dic['password']:
login_dic['username'] = username
login_dic['login'] =True
res = func(*args, **kwargs)
return res
else:
print('password is error')
return wrapper()
@auth_func
def index():
print('欢迎来到天猫购物商城')
@auth_func
def shoppingcar():
print('购物车:%s,%s,%s' % ('火锅底料', '三明治', '冰淇淋'))
index()
shoppingcar()
从上面的例子可以看出来我们用装饰器做了一个登录模块的验证功能的装饰器,验证用户是否登录成功,一个电商网站很多模块都要判断用户的的权限,只有用户登录成功,采用权限下单,支付,评价等等操作,我们不需要每一个模块都要验证用户的登录状态,只需要写一个判断登录权限的装饰器就完美解决了,大大的提高了代码的冗余和开发的效率。
四、介绍一个用户缓存模块的装饰器案例
缓存的应用场景:数据在需要频繁查询,且每次查询都需要大量计算或者等待时间之后才能返回结果的情况,使用缓存来提高查询速度,用内存空间换取查询、加载的时间。
那缓存应该采用什么数据结果呢?
1.便于查询的,且能快速获得数据的数据结构,每次查询的时候,只要输入一致,就应该得到同样的结果(顺序也一致,例如减法函数,参数顺序不一致,结果不一样)基于上面的分析,此数据结构应该是字典。
import time
import datetime
def cache(d={},cache_time=3):
def _cache(func):
def wrapper(*args,**kwargs):
if d.get(args)is None or datetime.datetime.now().timestamp()-d[args][1]>cache_time:
value = func(*args,**kwargs)
d[args] = (value,datetime.datetime.now().timestamp())
return value
else:
print('using cache')
print(d[args][0])
return d[args][0]
return wrapper
return _cache
@cache(cache_time=15)
def test_func(x,y):
print(x**y)
return x**y
test_func(1,2)
time.sleep(4)
test_func(1,2)
test_func(2,4)
test_func(2,4)
参考文献:https://blog.csdn.net/weixin_43936969/article/details/103823711
参考文献:https: // blog.csdn.net / maergaiyun / article / details /82724679
网友评论