python 装饰器

python 装饰器:

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

装饰器本质也是函数,(装饰其他函数)就是为其他函数添加附加功能.

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

#python解释器从上往下执行。
例一:

def foo():                //1.将函数放进内存
    print 'foo'
    
foo()                            //2.执行这个函数.去内存里面找到foo函数,执行里面的内容"print 'foo'"

foo                             //代表函数名,指向了内存地址。可以对foo重新赋值。。

例二:

foo = lambda x: x + 1
 
foo(2)           # 执行下面的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)这句,是简化的写法.使用语法糖@来装饰函数

@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']



原文地址:https://www.cnblogs.com/saneri/p/4992586.html