一.什么是装饰器
器指的是工具,而程序中的函数就具备某一功能的工具
装饰指的是为被装饰器对象添加额外功能
就目前的知识来看:
定义装饰器就是定义一个函数,只不过该函数的功能是用来为
其他函数添加额外的功能
其实:
装饰器本身其实可以是任意可调用的对象
被装饰的对象也可以是任意可调用的对象
二.为什么要用装饰器
软件的维护应该遵循开放封闭原则
开放封闭原则指的是:
软件一旦上线运行后对修改源代码是封闭的,对扩展功能的是开放的
这就用到了装饰器
装饰器的实现必须遵循两大原则:
1、不修改被装饰对象的源代码
2、不修改被装饰对象的调用方式
装饰器其实就在遵循1和2原则的前提下为被装饰对象添加新功能
三.如何使用装饰器
无参装饰器:
计算函数运行时间
import time def index(): start=time.time() print('welcom to index') time.sleep(3) stop=time.time() print('run time is %s' %(stop-start)) index()
import time def index(): print('welcome to index') time.sleep(3) def f2(): print('from f2') time.sleep(2) start=time.time() index() stop=time.time() print('run time is %s'%(stop-start)) start=time.time() f2() stop=time.time() print('run time is %s'%(stop-start))
装饰器修正:
import rime #时间模块 def timmer(func)
def wrapper(*args,**kwargs): #什么都能接收,也可以不传值 start=time.time() #计算开始时间 func(*args,**kwargs) stop=time.time() #计算结束时间 print('run time is %s'%(stop-start)) #输出所用时间 return wrapper #返回wrapper的内存地址 def index(): #定义一个名为index的函数 print('welcome to index') #执行时打印welcome to index time.sleep(3) #等待三秒钟 return 123 #返回值为123 可以没有 index=timmer(index) index()
#这样就不会修改被装饰对象的源代码和调用方式
基本格式 def deco(func): def wrapper(*args,**kwargs): res=func(*args,**kwargs) return res return wrapper
有参装饰器:
import time current_user={'user':None} def auth(engine='file'): def deco(func): def wrapper(*args,**kwargs): if current_user['user']: #已经登陆过 res = func(*args, **kwargs) return res user=input('username>>: ').strip() pwd=input('password>>: ').strip() if engine == 'file': # 基于文件的认证 if user == 'egon' and pwd == '123': print('login successful') # 记录用户登陆状态 current_user['user']=user res=func(*args,**kwargs) return res else: print('user or password error') elif engine == 'mysql': print('基于mysql的认证') elif engine == 'ldap': print('基于ldap的认证') else: print('无法识别认证来源') return wrapper return deco @auth(engine='mysql') # @deco #index=deco(index) #index=wrapper def index(): print('welcome to index page') time.sleep(1) @auth(engine='mysql') def home(name): print('welecome %s to home page' %name) time.sleep(0.5) index() home('egon')