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