装饰器
装饰器的推导过程
# 方案一: 代码冗余有,,如果很多地方调用index
# def index(x):
# time.sleep(2)
# print('welcome to %s' % x)
#
# start = time.time()
# index(11)
# stop = time.time()
# print(stop - start)
# 方案二: 写死了 改变了调用方式
# def index(x):
# time.sleep(2)
# print('welcome to %s' % x)
# def wrapper():
# start = time.time()
# index(11)
# stop = time.time()
# print(stop - start)
#
# wrapper()
# 方案三: 改变l调用方式
# def index(x):
# time.sleep(2)
# print('welcome to %s' % x)
# def wrapper(func):
# start = time.time()
# func(11)
# stop = time.time()
# print(stop - start)
#
# wrapper(index)
# 方案四: 参数写死了
# def index(x):
# time.sleep(2)
# print('welcome to %s' % x)
#
# def outer(func):
# def wrapper():
# start = time.time()
# func(11)
# stop = time.time()
# print(stop - start)
# return wrapper
#
# index = outer(index)
# index()
# 方案五: 装饰器完成
from functools import wraps
def outer(func):
@wraps(func) # 这个呢就是可以把index函数的内置方法伪装的和wrapper一样
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs) # 接受的是func的返回值
stop = time.time()
print(stop - start)
return res
return wrapper #outer的返回值
@outer # index = outer(index的内存地址) 调用wrapper
def index(x):
"""
qiufuwifiuqwf
:param x:
:return:
"""
time.sleep(2)
return 'welcome to %s' % x
多个装饰器
import time
def outer1(func1):
print('加载了outer1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outer2(func2):
print('加载了outer2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outer3(func3):
print('加载了outer3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outer1
@outer2
@outer3
def index(x):
time.sleep(2)
print('welcome to %s' % x)
index('egon')
===================================>
加载了outer3
加载了outer2
加载了outer1
执行了wrapper1
执行了wrapper2
执行了wrapper3
welcome to egon
"""
整个运行过程:
1.加载先是自下而上的,outer3(被装饰函数的index的内存地址) ---> 返回wraper3的内存地址
2.outer2(wraper3的内存地址)---->返回wraper2的内存地址
3.outer1(wraper2的内存地址)----->返回wraper1的内存地址
4.index = wraper1的内存地址
5.运行wraper2
6.运行wraper3
"""
结论:
加载顺序(外层函数的调用顺序):自下而上
执行顺序(wraper的执行顺序):自上而下
有参装饰器
import time
def login_auth(type = None):
def outer(func):
def wrapper(*args, **kwargs):
if type == 'file':
res = func(*args, **kwargs)
return res
else:
print('类型指定错误')
return wrapper
return outer
@login_auth('file')
def index(x):
time.sleep(2)
print('welcome to %s' % x)
index('egon')
@login_auth('mysql')
def home():
pass
home()
"""
有参装饰器的本质就是在外层,加一层函数,闭包传参的方式
"""
无参装饰器模板
def outer(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
有参装饰器模板
def auth(x):
def outer(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
return outer