设为首页 收藏本站
查看: 435|回复: 0

[经验分享] python之路第五篇之装饰器:(进阶篇)

[复制链接]

尚未签到

发表于 2015-11-30 11:54:49 | 显示全部楼层 |阅读模式
装饰器:

学前必备知识:
  

def f1():  print "f1"
  
  
f1() #表示函数执行
  
f1   #表示函数,指向内存地址
  
  
f1 = lambda x: x + 1
  
f1() # 执行这个lambda表达式,而不再是原来的f1函数,因为函数f1被重新定义了
  

装饰器代码剖析:
  假如有这么一个需求,公司临时规定将某块业务加上访问权限,因为代码太多,又不想改变原有已经封装好的
  
代码,于是乎,基础平台的同志们想出了这么一个解决办法:利用装饰器解决
  那么什么是装饰器?这个问题先留着,直接看代码:(代码剖析:)
  

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.py #代码名称
  

#!/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 #业务程序名称
  

#!/usr/bin/env python  #-*- coding:utf-8 -*-
  import bash
  bash.f1()  #调用bash.f1 方法
  
  

  执行业务程序 yw.py 结果如下:
  

auth user ...  
I'm f1
  
  

  显然上面已经达到我们的需求了,@auth_login 就是我们的装饰器,上面的列子就是对它使用的
  
其中一种方式;
  那么问题来了:如果平台需要再调用基础平台的 f2 方法,并且还是带参数的”传入参数“的方法去调用,
  
显然上面的程序已经不再满足需求了;
  那么我们可以不可以这么做?就是我们再另外定义另外一个装饰器,而这个装饰器是可以接受参数的;

代码如下:
  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函数的返回值给被装饰器的函数的函数名
  

装饰器返回值(return):

获取主机列表:
  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 之后再执行一个函数?

作业1:
  将如下三层装饰器用语言解释一遍:
  

#!/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/wupeiqi/articles/4980620.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145339-1-1.html 上篇帖子: Python之路【第三篇】:Python基础(二) 下篇帖子: 无需操作系统直接运行 Python 代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表