装饰器
开放封闭原则
软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的,也就是说我们必须要找到一种解决方案:
能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能。
总结
原则如下:
1、不修改源代码
2、不修改调用方式
目的:
在遵循1和2原则的基础上扩展新功能
装饰器:
器指的是工具,装饰指的是为被装饰对象添加新功能,
完整含义:
装饰器即在不修改被装饰对象源代码与调用方式的前提下, 为被装饰器的对象添加新功能。
装饰器与被装饰的对象均可以是任意可调用的对象
装饰器=======》函数
被装饰的对象=========》》函数
无参装饰器
import time def index(): star_time =time.time() time.sleep(1) print('welcome to index page') stop_time=time.time() print('run time is %s' %(stop_time-star_time)) index() #打印结果为 welcome to index page run time is 1.0006649494171143
修订方案一
import time def index(): time.sleep(1) print('welcome to index page') def home(name): time.sleep(2) print('welcome %s to home page '%name) star_time =time.time() index() stop_time=time.time() print('run time is %s'%(stop_time-star_time)) star_time=time.time() home('egon') stop_time =time.time() print('run time is %s'%(stop_time-star_time)) #打印结果: welcome to index page run time is 1.0000946521759033 welcome egon to home page run time is 2.0007834434509277 #修改方案一 此种方法麻烦, 每增加一个或更改 都要从新写一个代码。比较麻烦, 不推荐
import time def index(): time.sleep(1) print('welcome to index page') def home(name): time.sleep(2) print('welcom to home page'%name) def wrapper(func): star_time=time.time() func() stop_time =time.time() print ('run time is %s'%(stop_time-star_time)) wrapper(index)
修改方法二: #对于index( )的调用结果 welcome to index page run time is 1.0006787776947021 虽然实现了index()增加新功能作用但是却更改了调用方式改成了 wrapper(index)所以是不可以的 而对于home(name )这种有参函数却无法修改, 所以这种修改方式也是不可以的
import time def index(): time.sleep(3) print('welcom to index page') def outter(func): #func=原index def wrapper(): star_time=time.time() func() #原index 即打印welcom to index page stop_time=time.time() print(stop_time-star_time) # 算时间得结果 return wrapper #返回wrapper函数 index=outter(index) index() #针对index做的修改方案
无参装饰器升级版
import time def index(): time.sleep(1) print('welcom to index page') return 122 def home(name): time.sleep(2) print('welcome %s to home page'%name) def timmer(func): #func=原index 或者func=原home 所以这个func没有被固定死,可以为其赋不同的值 def wrapper(*args,**kwargs): star_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(stop_time-star_time) return res return wrapper index=timmer(index) home=timmer(home) index() home(name='egon') #打印结果 welcom to index page 1.0009210109710693 welcome egon to home page 2.000316619873047 升级最终版本 针对这种解决方案 就是用闭包函数 并把之前学过的 *args 与**kwargs 应用到此处 ,完美的解决
无参装饰器的模板 重点
def outer(func): def inner(*args,**kwargs): res=func(*args,**kwargs) return res return inner
语法糖
放在被装饰函数的正上方, 单独一行,修饰简洁 便于程序员理解,
import time def timmer(func): def wrapper(*args,**kwargs): star_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(stop_time-star_time) return res return wrapper @timmer #语法糖, 表示index =timmer(index) def index(): time.sleep(1) print('welcom to index page') return 122 @timmer #语法糖 表示 home=timmer(home) def home(name): time.sleep(2) print('welcom %s to home page'%(name)) index() home('egon')
认证装饰器
import time current_user={'username':None, } def auth(func): 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 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')
叠加装饰器
@timmer # timmer 统计的是auth+index的执行时间 @auth def index(): time.sleep(1) print('welcome to index page') return 122 index() @auth @timmer # timmer 统计的是index的执行时间 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()