装饰器的编写及使用
装饰器的开放封闭原则:源代码在线上尽量避免更改,也尽量避免调用方式的更改。
装饰器的本质是在不改变源代码的前提下,添加新的功能。使其原有的类和函数得以增加新的功能。
import time def timmer(func): def wrapper(*args,**kwargs): print(func) start = time.time() res = func(*args,**kwargs) end = time.time() print("run time is %s " %(end - start)) return wrapper @timmer # index = timmer(index) 这就是装饰器,没有改变index函数的代码,但是在运行index函数时,却有了运行时间。 def index(): print("welcome to world !!! ") index() #这个执行的index并不是原始的index函数,而是timmer里的wrapper函数
@timmer做的事情是:将@timmer下的那个函数作为参数,传给timmer。也就是timmer(index),然后把返回值赋值给index。
index = timmer(index),这里的返回值是timmer里的wrapper,也就是将wrapper赋值给index。所以执行index() 就是在执行wrapper()。
执行wrapper(),打印func。这个func就是一开始最原始的index的内存地址。也就是@timmer下面的那个index函数。
无参装饰器的使用实例:用*args,**kwargs去处理传给wrapper的参数。
import time def timmer(func): """ 计算代码的运行时间。 :param args: :param kwargs: :return: 时间差 """ def wrapper(*args,**kwargs): print(func) # 打印的func是index的内存地址。 #func函数被扩展前的调用代码 start_time = time.time() # 被修饰的函数 res = func(*args,**kwargs) #func函数别扩展后的代码 end_time = time.time() print("run time is %s " %(end_time-start_time)) return res return wrapper @timmer # @timmer实际上是 index = timmer(index) def index(*args,**kwargs): time.sleep(0.3) print("index") @timmer def home(name): time.sleep(0.2) print("home is %s " %(name)) @timmer def auth(name,password): """ 认证 :return: """ print("auth:",name,password) @timmer def my_max(x,y): print("my_max function") res = x if x>y else y return res res = my_max(1,22) # res = my_max(1,22) 就是在res = warpper(1,22) print("===",res) auth("wang","111") home("George") index() #index() 实际上是在执行inner
无参装饰器的最终版本:可以装饰任何函数的装饰器,其装饰器wrapper的参数是*args和**kwargs。
def timmer(func): """ 计算代码的运行时间的时间装饰器。 :param args: :param kwargs: :return: 时间差 """ def wrapper(*args,**kwargs): #wrapper的参数是*,**。这样就可以接收任何不同的数据。 print(func) # 打印的func是index的内存地址。 #func函数被扩展前的调用代码 start_time = time.time() #被修饰的函数 res = func(*args,**kwargs) #func函数别扩展后的代码 end_time = time.time() print("run time is %s " %(end_time-start_time)) return res return wrapper
有参装饰器:就是给装饰器函数加参数。
给函数加用户认证功能,是加在真是的函数被调用之前,在函数被调用之前做用户认证。
def auth(auth_type): """ 参数装饰器 :param auth_type: :return: """ def wapper(func): """ 认证功能装饰器 :param func: :return: """ print("AUTH",auth_type) def inner(*args,**kwargs): if auth_type == "file": print("func the function", func) name = input("username >>:") #加认证,这个位置是真正实现认证功能的位置 password = input("password >>:") if name == "wang" and password == "111": print("ok successfull") res = func(*args,**kwargs) #被附加装饰器执行的函数 return res else: print("error NO") elif auth_type == "SQL": print("MySQL,NB大了") return inner return wapper @auth(auth_type = "SQL") #有参数了 将原有的wapper在嵌套进一层,把auth_type搞成参数 def index(): print("welcome to index !!!1") print("有参数了。不要脸了") index()
作业:把用户的登录信息结构化的存入到文件里,在结构化的读出来。实现用户的认证功能。
不完整版:
import time current_login={'name':None,'login':False} #加一个标识,用户名和登录状态。这样就不需要在二次输入用户名和密码 def timmer(func): def wapper(*args,**kwargs): start_time = time.time() f = func() end_time = time.time() print("run time is %s " % (end_time - start_time)) return wapper def auth2(auth_type='file'): def auth(func): # print(auth_type) def wrapper(*args,**kwargs): if current_login['name'] and current_login['login']: #认证用户有值,直接执行认证后的执行函数。 res=func(*args,**kwargs) return res if auth_type == 'file': name=input('username: ') password=input('password: ') if name == 'wang' and password == '111': print('auth successfull') res=func(*args,**kwargs) current_login['name']=name #记录登录状态。 current_login['login']=True return res else: print('auth error') elif auth_type == 'sql': print('还他妈不会玩') return wrapper return auth @timmer @auth2(auth_type='file') #@auth #index=auth(index) def index(): print('welcome to inex page') @auth2() def home(): print('welcome to home page') #调用阶段 index() home()
------------- END -----------