01.装饰器
1.1 什么是装饰器?(What)
装饰器本质是函数,用来给其他函数添加新的功能
- 特点:
不修改调用方式、不修改源代码
1.2 装饰器的应用场景?(Where)
- 用户认证,判断用户是否登录
- 计算函数运行时间(算是一个功能、在项目里用的不多)
- 插入日志的时候
- redis缓存
1.3 为什么使用装饰器?(Why)
1.4 如何使用装饰器?(How)
1.4.1 装饰器求函数运行时间
import time
def timer(func):
def deco(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs)
stop_time = time.time()
print("running time is %s"%(stop_time-start_time))
return deco
@timer
def test1():
time.sleep(3)
print("in the test1")
test1()
1.4.2 三级装饰器
import time
def auth(auth_type):
print("auth func:",auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
print('运行前')
func(*args, **kwargs)
print('运行后')
return wrapper
return outer_wrapper
@auth(auth_type="local")
def home():
print("welcome to home page")
return "from home"
home()
1.5 装饰器在项目中应用场景
1.5.1 身份验证
user,passwd = 'aaa','123'
def auth(func):
def wrapper(username,password,*args,**kwargs):
if user == username and password == passwd:
print("User has passed authentication")
res = func(username,password,*args,**kwargs)
return res
else:
raise ValueError("非合法用户")
return wrapper
@auth
def home(username,password):
print("welcome to home page")
return "from home"
home('aaa','123')
1.5.2 记录日志
from functools import wraps
import traceback
def decoratore(func):
@wraps(func)
def log(*args,**kwargs):
try:
print("当前运行方法",func.__name__)
return func(*args,**kwargs)
except Exception as e:
print(traceback.format_exc())
return log
@decoratore
def test():
int('a')
pass
if __name__ == '__main__':
test()
''' 上面运行结果
当前运行方法 test
Traceback (most recent call last):
File "C:/Users/tom/Desktop/alipay_demo/aaa/t2.py", line 11, in log
return func(*args,**kwargs)
File "C:/Users/tom/Desktop/alipay_demo/aaa/t2.py", line 18, in test
int('a')
ValueError: invalid literal for int() with base 10: 'a'
22222
'''
1.5.3 redis缓存
第一步:查询redis缓存是否存在这个key
第二步:如果存在这个key,不用去mysql中查询,直接从redis中取出数据即可(减轻了mysql压力)
第三步:如果查询的key不存在,先到mysql中查询数据,让后设置到redis中,下次查询就有了
1.5.3.1 2B青年实现
- 2B青年每一个需要使用缓存的数据,我都写一个方法获取数据,再写一个方法处理缓存。
- 若需要用到缓存的地方越来越多,每一个都需要这么写一套代码,代码冗余繁琐。
from django.core.cache import cache
import time
def get_readed_cache():
key = 'readed'
if cache.has_key(key):
data = cache.get(key)
else:
data = "select name from tb"
cache.set(key, data, 3600 - int(time.time() % 3600))
return data
def test1():
data = get_readed_cache()
return data
def test2():
data = get_readed_cache()
return data
if __name__ == '__main__':
test1()
test2()
1.5.3.2 NB青年
- NB青年可以使用三级装饰器,在装饰器中判断key如果存在就从reids中获取,如果不存在就从数据库查询,并设置到reids中
from django.core.cache import cache
def redis_cache(key, timeout):
def __redis_cache(func):
def warpper(*args, **kw):
if cache.has_key(key):
data = cache.get(key)
else:
data = func(*args, **kw)
cache.set(key, data, timeout)
return data
return warpper
return __redis_cache
@redis_cache('test', 60)
def get_test_data():
data = '从数据库查询到了数据'
return data
if __name__ == '__main__':
get_test_data()