一、无参装饰器及其升级版
1 开放封闭原则
软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的。也就是说我们必须找到一种解决方案:能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能。
总结原则如下:
1、不修改源代码
2、不修改调用方式
目的:在遵循1和2原则的基础上扩展新功能
2、什么是装饰器?
器指的工具,装饰指的是为被装饰对象添加新功能。装饰器即在不修改被装饰对象源代码与调用方式的前提下,为被装饰器对象添加新功能。
装饰器与被装饰的对象均可以是任意可调用的对象
装饰器=》函数
被装饰的对象=》函数
3、给函数加上了功能,但改变了原代码
import time
def index():
start_time=time.time() #time.time()调的是1970年至现在一共过了多少秒
time.sleep(3)
print('welcome to index page')
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
index()
4. 没有把常用功能抽象成函数,需要反复输入
import time
def index():
time.sleep(3)
print('welcome to index page')
def home(name):
time.sleep(5)
print('welcome %s to home page' %name)
start_time=time.time()
index()
stop_time = time.time()
print('run time is %s' % (stop_time - start_time))
start_time=time.time()
home('egon')
stop_time = time.time()
print('run time is %s' % (stop_time - start_time))
5、修改了原函数的调用方式,即无法用index()的形式直接调用
import time
def index():
time.sleep(3)
print('welcome to index page')
def home(name):
time.sleep(5)
print('welcome %s to home page' %name)
def wrapper(func): #func=index
start_time=time.time()
func() #index()
stop_time = time.time()
print('run time is %s' % (stop_time - start_time))
wrapper(index) # 修改了原函数的调用方式
6、 初步解决了问题,但没有考虑到原参数带返回值,或带参数的情况
import time
def index():
time.sleep(3)
print('welcome to index page')
def outter(func): #func=最原始的index
# func=最原始的index
def wrapper():
start_time=time.time()
func()
stop_time=time.time()
print(stop_time-start_time)
return wrapper
index=outter(index) # 新的index=wrapper
index() #wrapper()
7、 考虑了原参数带返回值或参数的问题,但每次都要加上index=timmer(index)
import time
def index():
time.sleep(1)
print('welcome to index page')
return 122
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
#==============装饰器
def timmer(func):
#func=最原始的home
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs) #调用最原始的home
stop_time=time.time()
print(stop_time-start_time)
return res
return wrapper
index=timmer(index) # 新的index=wrapper
home=timmer(home) #新的home=wrapper
# ==========================================
index()
home('egon')
无参装饰器模板
def outer(func):
def inner(*args,**kwargs):
res=func(*args,**kwargs)
return res
return inner
8、运用装饰器语法糖 @timmer #index=timmer(index)
@timmer必须放在原函数的正上方,
timmer的函数体要放在@timmer之前
如果要用装饰器加@。。。,如果不用注释掉@
import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print(stop_time-start_time)
return res
return wrapper
@timmer #index=timmer(index)
def index():
time.sleep(1)
print('welcome to index page')
return 122
@timmer # home=timmer(home)
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
index()
home('egon')
9、认证装饰器实现(另一个例子)
import time
current_user={
'username':None,
# 'login_time':None
}
def auth(func):
# func=index
def wrapper(*args,**kwargs):
if current_user['username']:
print('已经登陆过了')
res=func(*args,**kwargs)
return res
uname=input('用户名>>: ').strip()
pwd=input('密码>>: ').strip()
if uname == 'egon' and pwd == '123':
print('登陆成功')
current_user['username']=uname
res=func(*args,**kwargs)
return res
else:
print('用户名或密码错误')
return wrapper
@auth #index=auth(index)
def index():
time.sleep(1)
print('welcome to index page')
return 122
@auth
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
index()
home('egon')
10、叠加多个装饰器,上面的装饰器作用为:下方装饰器+原函数
import time
current_user={
'username':None,
# 'login_time':None
}
def auth(func):
# func=index
def wrapper(*args,**kwargs):
if current_user['username']:
print('已经登陆过了')
res=func(*args,**kwargs)
return res
uname=input('用户名>>: ').strip()
pwd=input('密码>>: ').strip()
if uname == 'egon' and pwd == '123':
print('登陆成功')
current_user['username']=uname
res=func(*args,**kwargs)
return res
else:
print('用户名或密码错误')
return wrapper
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print(stop_time-start_time)
return res
return wrapper
@timmer # timmer 统计的是auth+index的执行时间
@auth
def index():
time.sleep(1)
print('welcome to index page')
return 122
index()
二、有参数的装饰器 #再包上一层,函数的参数可以为一个,也可为多个
import time
current_user={
'username':None,
# 'login_time':None
}
def auth(engine):
# engine='file'
def auth2(func):
# func=index
def wrapper(*args,**kwargs):
if engine == 'file':
if current_user['username']:
print('已经登陆过了')
res=func(*args,**kwargs)
return res
uname=input('用户名>>: ').strip()
pwd=input('密码>>: ').strip()
if uname == 'egon' and pwd == '123':
print('登陆成功')
current_user['username']=uname
res=func(*args,**kwargs)
return res
else:
print('用户名或密码错误')
elif engine == 'mysql':
print('基于MyQL的认证')
elif engine == 'ldap':
print('基于LDAP的认证')
return wrapper
return auth2
@auth('ldap') #@auth2 #index=auth2(index) #index=wrapper
def index():
time.sleep(1)
print('welcome to index page')
return 122
index() # wrapper()