装饰器定义:
本质是函数, 装饰其他函数就是为其他函数添加附加功能。
例:我想给下面几个函数加上一个记录日志的功能。
def test1(): pass def test2(): pass test1() test2()
按照以前所学的可以这样写。
1 def logger(): 2 #定义一个记录日志的函数 3 print("logging") 4 def test1(): 5 #这是一个test1()函数 6 pass 7 logger() #调用记录日志函数 8 9 def test2(): 10 # 这是一个test2()函数 11 pass 12 logger() #调用记录日志函数 13 14 test1() 15 test2()
如果按照上面这种修改方式,正在运行的程序就会暂停,会导致整个程序出错,如果改的不好还会使整个系统崩溃。
所以就出现了装饰器来弥补这个问题。不能改变函数本身源代码
使用装饰器原则:
1、不能修改被装饰的函数的源代码
2、不能修改被装饰的函数的调用方式。
高阶函数 + 嵌套函数 ===》 装饰器
装饰器第一阶段:
1 import time 2 #通过嵌套函数+高阶函数生成一个装饰器。 3 def timmer(func): 4 def deco(): 5 start_time = time.time() 6 func() 7 stop_time = time.time() 8 print("the func run time is %s" %(stop_time-start_time)) 9 return deco 10 11 @timmer # 相当于下面的test1=timmer(test1) 12 def test1(): 13 time.sleep(3) 14 print("in the test1") 15 @timmer # 相当于下面的test2=timmer(test2) 16 def test2(): 17 time.sleep(3) 18 print("in the test2") 19 20 # test1=timmer(test1) 21 test1() 22 # test2=timmer(test2) 23 test2()
执行结果:
装饰器第二阶段:当被装饰的函数中加上参数
1 import time 2 #通过嵌套函数+高阶函数生成一个装饰器。如果被修饰有多个变量。 3 #当test2()有多个变量时,装饰器如何写。 4 def timmer(func): #func=test2 5 def deco(): 6 start_time = time.time() 7 func() 8 stop_time = time.time() 9 print("the func run time is %s" %(stop_time-start_time)) 10 return deco 11 12 @timmer # 相当于下面的test1=timmer(test1) 13 def test1(): 14 time.sleep(3) 15 print("in the test1") 16 @timmer # 相当于下面的test2=timmer(test2) 17 def test2(name,age): #test2有多个变量时 18 print("in the test2",name,age) 19 20 # test1=timmer(test1) 21 test1() 22 # test2=timmer(test2) 23 test2("zhang3",18)
上面的代码中将test2()加了两个变量,这时再使用上面的装饰器时就会出错,提示少了两个位置参数。
执行结果:
这时就要修改装饰器。装饰器修改如下:
1 import time 2 #通过嵌套函数+高阶函数生成一个装饰器。如果被修饰有多个变量。 3 #当test2()有多个变量时,装饰器如何写。 4 def timmer(func): #func=test2 5 #这是一个装饰器,作用:增加一个函数运行时间。 6 def deco(*args,**kwargs): #加两种参数组。 7 start_time = time.time() 8 func(*args,**kwargs) #或者func(args,kwargs) 9 stop_time = time.time() 10 print("the func run time is %s" %(stop_time-start_time)) 11 return deco 12 13 @timmer # @timmer叫做语法糖,相当于下面的test1=timmer(test1) 14 def test1(): 15 #这时test1()函数。 16 time.sleep(3) 17 print("in the test1") 18 @timmer # @timmer叫做语法糖,相当于下面的test2=timmer(test2) 19 def test2(name,age): #test2有多个变量时 20 #这时test2函数。 21 print("in the test2",name,age) 22 23 # test1=timmer(test1) 24 test1() 25 # test2=timmer(test2) 26 test2("zhang3",18)
执行结果:
装饰器第三阶段:
案例:
公司网站有页面,一个页面一个函数,以前谁都可以登陆,现在加部分页面需要登陆才能查看页面。home页面登陆验证,bbs页面需要ldap验证,这里模拟一下ldap验证。
1 #装饰器 --- 网站登录设计 2 # 公司网站有页面,一个页面一个函数,以前谁都可以登陆,现在加部分页面需要登陆才能查看页面。 3 #home页面登陆验证,bbs页面需要ldap验证,这里模拟一下ldap验证。 4 username , password = "abc","123" 5 6 def auth(auth_type): 7 def out_warpper(func): 8 def warpper(*args,**kwargs): 9 if auth_type == "local": 10 user = input("username:") 11 pwd = input("password:") 12 if user == username and pwd == password : 13 res = func(*args,**kwargs) 14 return res 15 else: 16 exit("用户名或密码错误") 17 elif auth_type =="ldap": 18 user = input("username:") 19 pwd = input("password:") 20 if user == username and pwd == password: 21 func(*args, **kwargs) 22 print("我不会写外接") 23 else: 24 exit("用户名或密码错误") 25 return warpper 26 return out_warpper 27 28 def index(): 29 print("welcome to index") 30 31 @auth(auth_type = "local") 32 def home(name): 33 print("%s welcome to home"%(name)) 34 return "home给一个返回值" 35 36 @auth (auth_type = "ldap") 37 def bbs(): 38 print("welcome to bbs") 39 40 41 print(home("大哥")) #显示home返回值。看下返回值是否改变。 42 bbs()