python 从小白开始 - 装饰器

装饰器定义:

  本质是函数, 装饰其他函数就是为其他函数添加附加功能。

例:我想给下面几个函数加上一个记录日志的功能。  

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()

猜你喜欢

转载自www.cnblogs.com/ershier/p/9426285.html