装饰器: 1.本质:是函数 (装饰其他函数)为其他函数添加附加功能 2.原则:(1)不能修改被装饰的函数的源代码(不能需要增加功能的函数的源代码) (2)不能修改被装饰的函数的调用方式 实现装饰器的相关知识: 1.函数即“变量”(即把函数体赋值给函数名) 2.高阶函数(A把一个函数名当做实参传给另外一个函数(不修改被装饰函数的源代码的情况下)、B返回值中包含函数名) {A:实现新功能不修改源代码 import time def test(func): start_time=time.time() func() #相当于运行bar()----------高阶函数的运用 stop_time=time.time() print("fun time %s" %(stop_time-start_time)) def bar(): time.sleep(3) print("bar") test(bar) #func=bar 传递的是一个内存地址 不能传bar(),因为传的只是函数体,不是内存地址 #----------------------------------------------------------------- B:实现新功能不修改源代码且调用方式相同 import time def bar(): time.sleep(3) print("bar") def test(func): print(func) return func #返回一个内存地址,使调用方式能和原来相同相同 bar=test(bar) bar() #做到了不修改源代码且调用方式依然相同的高阶函数(新的覆盖旧的)3.嵌套函数 def boo(): print("in the boo") def too(): print("in the too") too() boo() #------------------------------------- 高阶函数+嵌套函数=装饰器 #-------**********为test1和test2分别加上统计运行时间的功能(装饰器实现)***********------ # Author:barry allen # -*- coding:utf-8 -*- import time def timer(func): def deco(): start_time=time.time() func() stop_time=time.time() print("fun time is %s"%(stop_time-start_time)) return deco @timer #相当于test1=timer(test1) def test1(): time.sleep(3) print("in the test1") @timer def test2(): time.sleep(3) print("in the test2") test1() test2() #如test1(),先走装饰器定义,然后转到被装饰的函数,func获取该函数的地址空间,等到调用test1()的时候再走装饰器新增的功能定义(即走deco()) #*---------------------------不确定参数的装饰器 # Author:barry allen # -*- coding:utf-8 -*- import time def timer(func): def deco(*args,**kwargs): #调用时没有传进参数,则为空,如果有传参数,则匹配对应的参数 start_time=time.time() func(*args,**kwargs) stop_time=time.time() print("fun time is %s"%(stop_time-start_time)) return deco @timer def test1(name,age): time.sleep(3) print("test1",name,age) # @timer # def test2(): # time.sleep(3) # print("in the test2") test1("林",12) # test2() #---------装饰器简单应用------------ # -*-coding:utf-8 -*- user,passwd='lin','123' def auth(func): def wrapper(*args,**kwargs): username = input("username:").strip() password= input("password").strip() if user==username and passwd==password: print("\033[32;1muser has passed \33[0m") func(*args,**kwargs) '''res=func(*args,**kwargs) return res 如果源代码修改且有返回结果输出,此时在装饰器要这样写法才不会丢失有返回结果的新源代码函数 ''' else: exit("\033[31;1mfailed \33[0m") return wrapper def index(): print( "welcome to the index page") @auth def home(): print("welcome to the home page") #return "from home" 接上个注释说明 @auth def bbs(): print("welcome to the bbs page") index() home() #print(home()) bbs() #-----------进阶应用 #装饰器可以定义不同的类型传进装饰器的参数,并在装饰器里面根据条件判断 __author__ = "Alex Li" import time user,passwd = 'alex','abc123' def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:", *args, **kwargs) if auth_type == "local": username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1mUser has passed authentication\033[0m") res = func(*args, **kwargs) # from home print("---after authenticaion ") return res else: exit("\033[31;1mInvalid username or password\033[0m") elif auth_type == "ldap": print("ldap......") return wrapper return outer_wrapper def index(): print("welcome to index page") @auth(auth_type="local") # home = wrapper() def home(): print("welcome to home page") return "from home" @auth(auth_type="ldap") def bbs(): print("welcome to bbs page") index() print(home()) #wrapper() bbs()