python 装饰器详解编程语言

python 装饰器:

装饰器的作用就是在函数调用方法不变的情况下,把一个函数封装到另一个函数里面,执行这个函数时自己去调用另一个函数.

一、了解装饰器之前,先看看下面这个列子.

 1 #python解释器从上往下执行。 
 2 例一: 
 3  
 4 def foo():                //1.将函数放进内存 
 5     print 'foo' 
 6      
 7 foo()                            //2.执行这个函数.去内存里面找到foo函数,执行里面的内容"print 'foo'" 
 8  
 9 foo                             //代表函数名,指向了内存地址。可以对foo重新赋值。。 
10  
11 例二: 
12  
13 def foo(): 
14     print 'foo' 
15   
16 foo = lambda x: x + 1 
17   
18 foo()           # 执行下面的lambda表达式,而不再是原来的foo函数,因为函数 foo 被重新定义了

再看看下面这段代码,能看懂就离学会装饰器不远了.

1 ########################################## 
2 def f1(arg):                 
3     arg() 
4          
5 def func(): 
6  
7     print "12" 
8      
9 f1(func)    

#我们可以简单的看看它的执行顺序:

———————————————————-
1、执行def f1(arg): 将其放进内存地址.内容不执行.
2.执行def func():将其放进内存地址,内容不执行.
3.执行f1(func) 给f1传的参数为func,这个参数为func()函数.

4.执行def f1(arg):    ===> arg = func ===> arg() ==func()

5.执行arg()      ==>  func()

6.执行def func(): 函数
7. 执行 print “12”

总结:把一个函数func()封装到另一个函数f1(arg)里面,执行这个函数f1(func)时自己去调用另一个函数.

 下来我们就看看装饰器到底是什么鬼:

1.使用单层装饰函数在函数执行前和执行后分别附加额外功能:

 1 #替换函数(装饰) 
 2 #装饰函数的参数是被装饰的函数对象,返回原函数对象 
 3 #装饰的实质语句: myfunc = deco(myfunc) 
 4  
 5 def deco(func): 
 6  
 7     print "before" 
 8      
 9     func() 
10      
11     print "after" 
12      
13     return func 
14   
15 def myfunc(): 
16  
17     print "myfunc" 
18   
19 myfunc = deco(myfunc)           #重新定义了一个myfunc,指向deco(myfunc),这样可以不用改变调用函数的名称.
20

21 myfunc()            #调用函数.

2.使用双层装饰函数来给函数附加额外功能:

 1 def auth(func):                #func = f1 ==> func() <==> f1() 
 2      def inner():          
 3        print "before"             
 4        func()                            #==> func() == f1() 原函数. 
 5     
 6      return inner                #返回的 inner,inner代表的是函数,非执行函数 
 7  @auth     
 8  def f1(): 
 9   
10     print "1" 
11  #--------------------------------------------------------------------  
12  f1()            #调用函数,在调用函数名不变的情况下,先执行装饰函数中的inner()块,在执行f1()函数. 
13   
14 15   
16   
17  
18 @auth  <==> f1 = auth(f1)这句,[email protected]

@auth 等于函数执行了两次:
          1.执行auth函数,把被装饰的函数作为参数auth(foo)
          2.将auth函数的返回值,赋值给被装饰的函数的函数名.

那么问题来了,被装饰的函数如果有参数呢?

下来看看装饰带参数的函数:

 1 def  decc(args): 
 2     def inner(a): 
 3         print "before!!!"           #装饰前验证 
 4         args(a) 
 5         print "after!!!"       #装饰后打印loggin 
 6     return inner 
 7  
 8 @decc 
 9 def f1(a): 
10     print "hello f1 is %s" %a 
11  
12 #--------------------------------------------------- 
13 f1(10) 
14  
15  
16 before!!! 
17 hello f1 is 10 
18 after!!!

装饰器之动态参数:

 1 def auth(func): 
 2     def inner(*args, **kwargs): 
 3         print 'before' 
 4         func(*args,**kwargs) 
 5         print 'after' 
 6     return inner 
 7  
 8 @auth 
 9 def f5(arg): 
10     print 'f5',arg 
11  
12  
13 调用函数: 
14 f5("1111" ) 
15 f5("2" "3" "4" ) 
16  
17 执行结果如下: 
18  
19 before 
20 f5 1111 
21 after 
22 -------------------------------- 
23 before 
24 f5 2 3 4 
25 after

 装饰含返回值的函数:

 1 def auth(func): 
 2     def inner(*args, **kwargs): 
 3         print 'before' 
 4         func(*args,**kwargs) 
 5         print 'after' 
 6         return func(*args,**kwargs)             #如果没有这个return,则执行函数调用时将返回none 
 7     return inner 
 8  
 9 @auth 
10 def fetch_server_list(arg): 
11     print "fetch is ",arg 
12     server_list = ['c1','c2','c3'] 
13     return server_list

调用:

ret_list = fetch_server_list('test')

print ret_list


执行结果:

before

 after
 [‘c1’, ‘c2’, ‘c3’]


 下面我们来看一个简单的完整的用户登录认证的装饰器函数:

 1 def login():          #用户登录认证函数 
 2     name = 'saneri' 
 3     if name == 'saneri': 
 4         return True 
 5     else: 
 6         return False 
 7  
 8 def auth(func):          #装饰器函数. 
 9     def inner(*args, **kwargs): 
10         is_login = login()    #调用login()函数 
11         if not is_login:      #如果登录成功则往下执行,负责返回“非法请求” 
12             return "非法请求!" 
13         temp = func(*args, **kwargs) 
14         print 'after!' 
15         return temp 
16     return inner 
17  
18 @auth 
19 def fetch_server_list(arg):      #被装饰函数. 
20     server_list = ['c1','c2','c3','c4'] 
21     return server_list


函数调用:

ret = fetch_server_list('test')  

print ret
#用户登录成功则输出如下------

after!
[‘c1’, ‘c2’, ‘c3’, ‘c4’] 



 用户登录认证过程传入参数实现:

#装饰器实现token验证:
1
def login(token): 2 loacl = "11jfdsajfdfdddlla999"      #定义一个key值.用于和调用时的key做比较,如果相同则认证通过. 3 if loacl == key: 4 return True 5 else: 6 return False 7 #auth()为装饰器函数 8 def auth(func): 9 def inner(*args, **kwargs): 10 #key = kwargs['token']    //去字典里获取key的值token 11 #del = kwargs['token']    //原fetch_server_list只接收一个参数,所以在删掉key的值 12 key = kwargs.pop('token')   #去字典里把key拿出来,然后在删掉,这一句是上面两句的结合版. 13 is_login = login(key) 14 if not is_login: 15 return "非法请求!" 16 temp = func(*args, **kwargs) 17 print 'after!' 18 return temp 19 return inner 20 21 @auth 22 def fetch_server_list(arg): 23 server_list = ['c1','c2','c3','c4'] 24 return server_list

#调用:
key = "11jfdsajfdfdddlla999"
ret = fetch_server_list('test',token=key)
print ret

#输出

after!
[‘c1’, ‘c2’, ‘c3’, ‘c4’]



 

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/11674.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论