def f1(): print "f1" f1() #表示函数执行 f1 #表示函数,指向内存地址 f1 = lambda x: x + 1 f1() # 执行这个lambda表达式,而再也不是原来的f1函数,由于函数f1被从新定义了
假若有这么一个需求,公司临时规定将某块业务加上访问权限,由于代码太多,又不想改变原有已经封装好的
代码,因而乎,基础平台的同志们想出了这么一个解决办法:利用装饰器解决html
那么什么是装饰器?这个问题先留着,直接看代码:(代码剖析:)python
def auth_login(func): # func = f1 ,func() = f1() def inner(): print "welcome to login ..." #验证的内容加在这里 func() # func() = f1() #至关于执行f1() reture inner # 返回 inner函数体 def f1(): #print "welcome to login ..." #需求是在这块加上验证(那么怎么实现?) print "f1..." result = auth_login(f1) #等于inner函数(包括它下面那一段代码) f1 = result f1() #函数执行
基础平台代码:(在业务平台不须要修改调用方式的时候,直接调用基础平台这块代码)bash
bash.py #代码名称app
#!/usr/bin/env python #-*- coding:utf-8 -*- def auth_login(func): def inner(): print "auth user ..." # 认证模块 func() return inner @auth_login #@auth_login 是python默认封装好的一种方法,#至关于 result=auth_login(f1) # f1() = result()#(和上面的执行效果同样) def f1(): print "I'm f1" def f2(): print "I'm f2" f1() #函数执行,这个是属于业务部门来调用执行的,单独拿出来调用,以下:
业务部门调用bash.py函数下的某个方法:函数
yw.py #业务程序名称fetch
#!/usr/bin/env python #-*- coding:utf-8 -*- import bash bash.f1() #调用bash.f1 方法
执行业务程序 yw.py 结果以下:code
auth user ... I'm f1
显然上面已经达到咱们的需求了,@auth_login 就是咱们的装饰器,上面的列子就是对它使用的
其中一种方式;server
那么问题来了:若是平台须要再调用基础平台的 f2 方法,而且仍是带参数的”传入参数“的方法去调用,
显然上面的程序已经再也不知足需求了;htm
那么咱们能够不能够这么作?就是咱们再另外定义另一个装饰器,而这个装饰器是能够接受参数的;blog
bash.py #代码名称
def auth_login(func): def inner(): print "auth user ..." func() return inner def auth_arg_login(func): #这块代码是新加入的,传入参数 def inner(arg): #参数 print "auth user arg ..." func(arg) return inner @auth_login def f1(): print "I'm f1" @auth_arg_login # 调用新装饰器 def f2(arg): #参数 print "I'm f2",arg
业务部门再次调用bash.py函数下的方法:
yw.py #业务程序名称
#!/usr/bin/env python #-*- coding:utf-8 -*- import bash base.f1() base.f2(”new programs") # 传入参数
执行业务程序 yw.py 结果以下:
auth user ... I'm f1 auth user arg ... #这块输出 I'm f2 new programs #这块输出
这个时候,需求又变了,业务部门说,咱们须要传递2个参数,因而乎,基础平台啪啪啪,又写了几个方法,
又实现了,过了一段时间,业务平台的同志来的时候说了一句话,兄弟,很差意思,我还须要传递几个参数,
这个时候基础平台的同志发现本身快疯了,CTO 老大看不下去了,这个时候,他告诉基础平台这么一个方法,
也就是下面的代码(传递动态参数)
bash.py #代码名称
#!/usr/bin/env python #-*- coding:utf-8 -*- def auth_login(func): def inner(*arg,**kwagrs): #动态参数 print "auth user ..." #认证模块 func(*arg,**kwargs) #动态参数 return inner @auth_login #在函数上面加上这么一句 @auth_login: 这个是python默认封装好的一种方法, #至关于 result = auth_login(f1) # f1() = result() #(和上面的执行效果同样) def f1(arg): print "I'm f1",arg
业务部门调用bash.py函数下的某个方法:
yw.py #业务程序名称
#!/usr/bin/env python #-*- coding:utf-8 -*- import bash bash.f1('test') #调用bash.f1 方法
执行业务程序 yw.py 结果以下:
auth user ... I'm f1 test # 执行结果
1.装饰器是一个函数 2. 执行auth_login 函数,被装饰的函数做为参数auth_login(f1) auth_login 函数的返回值, 赋值给被装饰的函数的函数名 @auth_login def f1(): pass 3.动态参数,能够装饰含有n个参数的函数 4.函数返回值 5.多装饰器 6.至少3层,3层的如何使用? @auth_login 1.执行auth_login函数 2.将auth_login函数的返回值给赋值给被装饰器的函数的函数名 @auth_login(arg) 1.执行auth_login函数,获得返回值,result 2.建立装饰器,@ + result结合:@result 3... 1).执行result 函数 2).将result函数的返回值给被装饰器的函数的函数名
bash.py #代码名称
def auth_login(func): def inner(*arg,**kwargs) print "welcome to login..." temp = func(*arg,**kwargs) print "login after..." return temp return inner @auth_login def fetch_server_list(): server_list = ['server1','server2','server3'] return server_list
执行业务程序 yw.py 结果以下:
import base server_list = base.fetch_server_list('test') print server_list
程序执行结果:
welcome to login... login after... ['server1', 'server2', 'server3']
上面的列子说了这么多,好,如今咱们来作一个用户登录验证:
def login(): # 这里定义一个login 函数 name = "Allen" # 若是这里是“Allen“,则下面的函数调用,验证成功,不然失败 if name == "Allen": return True else: return False def auth_login(func): def inner(*arg,**kwargs): is_login = login() #这里加入一个验证判断 if not is_login: print "非法用户" print "welcome to login..." temp = func(*arg,**kwargs) print "login after..." return temp return inner @auth_login def fetch_server_list(arg): server_list = ['server1','server2','server3'] return server_list
执行业务程序 yw.py 结果以下:
import base server_list = base.fetch_server_list('test') print server_list
welcome to login... login after... ['server1', 'server2', 'server3']
若是name = ”aaaa“, 不是”Allen“,则执行结果:验证失败:
非法用户 welcome to login... login after... ['server1', 'server2', 'server3']
那么又有人问,这个有个鸟用,我还须要密码验证,那么这个怎么作呢?
少废话,直接上代码:
def login(key): local_key = "123456" #这里作个一个key验证 if local_key == key: return True else: return False def auth_login(func): def inner(*arg,**kwargs): #key = kwargs['token'] #注意这里 #del kwargs['token'] key = kwargs.pop('token') #这一句等于 上面注释的两句 #这句含义:由于下面的login 只接受一个参数,这里多一个参数,全部删除 is_login = login(key) #注意这里 if not is_login: print "非法用户" print "welcome to login..." temp = func(*arg,**kwargs) print "login after..." return temp return inner @auth_login def fetch_server_list(arg): server_list = ['server1','server2','server3'] return server_list
执行业务程序 yw.py 结果以下:
import base server_list = base.fetch_server_list('test',token=‘key1111’) #注意这里 print server_list
@auth_login @auth_login def f1(): pass 执行的结果: 就是一层套一层
双装饰用途:
双层装饰器,能够用在如下途径: 好比用户权限管理,第一层装饰器用于用户名密码验证, 第二层用在 判断用户是什么身份的用户,好比:普通用户,超级用户等
需求又来了,在上面获取 fetch_server_list 以前执行一个函数,
可不能够在fetch_server_list 以后再执行一个函数?
将以下三层装饰器用语言解释一遍:
#!/usr/bin/env python #coding:utf-8 def Before(request,kargs): print 'before' def After(request,kargs): print 'after' def Filter(before_func,after_func): def outer(main_func): def wrapper(request,kargs): before_result = before_func(request,kargs) if(before_result != None): return before_result; main_result = main_func(request,kargs) if(main_result != None): return main_result; after_result = after_func(request,kargs) if(after_result != None): return after_result; return wrapper return outer @Filter(Before, After) def Index(request,kargs): print 'index'
原文连接: http://www.cnblogs.com/yangyinghua/p/4987290.html