python装饰器--原来如此简单,python装饰器原理详解_1

  python装饰器--原来如此简单,python装饰器原理详解

  1.对装修工的理解

  Decorator的目的是将一个函数嵌入到另一个函数中重复使用,不改变其结构,不增加函数的使用,但不用写太多冗余代码;

  装饰器本质上是一个Python函数,它允许其他函数在不修改任何代码的情况下添加额外的函数。装饰器的返回值也是一个函数对象。

  常用功能:1。介绍日志;2.函数执行时间统计;3.执行活动前的准备工作;4.执行完函数后清理函数;5.权限验证;6.躲藏

  2.实现原理和一般编写方法

  我们可以从一个简单的记录函数运行时间的装饰物中举一反三,推导出一个通用的装饰物编写方法。

  进口时间

  deftimer(func):

  记录方法运行时的装饰器。

  :paramfunc:方法

  :返回:函数对象

  defdeco(*args,**kwargs):

  startTime=time.time()

  f=func(*args,**kwargs)

  endTime=time.time()

  毫秒=(结束时间-开始时间)*1000

  打印(时间为% dms %毫秒)

  Returnf#如果func有返回值,需要在这里返回;否则,默认返回值为None,这通常是默认情况下返回的。

  returndeco

  @定时器

  默认测试(参数):

  print( tests running!)

  时间.睡眠(1)

  ReturnReturnedvalue#这个函数有一个返回值,所以你需要在decorator的deco方法中写返回值。

  t=测试(“aa”)

  Print(t)这是一个非常简单通用的记录时间的装饰品,从而推导出一个通用的装饰品书写方法:

  :#自定义装饰函数名

  Defdeco(*args,**kwargs):#原封不动地传递所有参数。

  Print(在函数运行到此分割线以上之前编写操作)

  # -分模线

  f=func(*args,**kwargs)

  # -

  ---------分割线-----------

  print("在这个分割线之后,return之前,写函数运行后的操作")

  returnf#如果func有返回值得话,需要在此return回去,否则,默认返回值为None,一般默认都返回

  

  returndeco

  

  

  @func_name

  deftest(parameter):#8

  print("testisrunning!")

  time.sleep(1)

  return"Returnedvalue"#该函数有返回值,所以需要在装饰器中的deco方法中写返回值

  

  

  t=test('aa')

  print(t)ok 装饰器到此可以完事了,一般情况下都能满足需求了,网上看那么多原理,有点儿浪费时间,我偏向实操型,实在不喜欢啰嗦那么多,就是干。

  当然在开发过程中, 我们可能会遇到一些特殊情况,比如参数问题

  1、给装饰器函数代参数(通用)

  2、将执行函数的参数拆分计算等(比如:1000w的数据,拆分成100份执行等)(定制)

  那就按顺序来

  1、写一个代参数的装饰器

  

deflogging(level):

  defwrapper(func):

  definner_wrapper(*args,**kwargs):

  print("[{level}]:enterfunction{func}()".format(level=level,func=func.__name__))

  returnfunc(*args,**kwargs)

  returninner_wrapper

  returnwrapper

  

  @logging(level='INFO')

  defsay(something):

  print("say{}!".format(something))

  

  #如果没有使用@语法,等同于

  #say=logging(level='INFO')(say)

  

  @logging(level='DEBUG')

  defdo(something):

  print("do{}...".format(something))

  

  if__name__=='__main__':

  say('hello')

  do("mywork")

发现:就是在上面的通用的模板上又套了一层!!!,然后拿到里面的参数即可! so easy!!!

  2、写一个参数拆分的装饰器,这个就稍微有点定制型了,不能像上面的一样通用了,举个 栗子:

  

deffunc_name(func):#自定义装饰器函数名

  defdeco(*args,**kwargs):#将所有参数原封不动的进行传递

  print(args[0])

  f_list=[]

  foriinrange(0,args[0],100000):

  print(i)

  f_list.append(func(i))

  #f_list#这儿应该按照既定规则,继续对这个结果进行拼接,如果是写文件、入库等操作,可以不用return

  returnf_list#这儿如果有返回值得话,应该是

  

  returndeco

  

  @func_name

  deftest(parameter):#8

  print("testisrunning!")

  time.sleep(1)

  return"Returnedvalue"#该函数有返回值,所以需要在装饰器中的deco方法中写返回值

  

  

  t=test(1000000)

  print(t)

可以看出来,这个的定制性稍微高点,不通用,但是我们实现了我们的需求,所以,我们最应该理解并学会的是怎么用!!!

  可以看出来,这个的定制性稍微高点,不通用,但是我们实现了我们的需求,所以,我们最应该理解并学会的是怎么用!!!

  下面在介绍一下基于类实现的装饰器,那问题来了,我是实战派,我并没有用类装饰器的需求,所以,当个大盗吧,以后用到了不至于瞎找了!!!

  装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重载了__call__()方法,那么这个对象就是callable的。

  

classTest():

  def__call__(self):

  print'callme!'

  t=Test()

  t()#callme

像__call__这样前后都带下划线的方法在Python中被称为内置方法,有时候也被称为魔法方法。重载这些魔法方法一般会改变对象的内部行为。上面这个例子就让一个类对象拥有了被调用的行为。

  回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文)。

  那么用类来实现也是也可以的。我们可以让类的构造函数__init__()接受一个函数,然后重载__call__()并返回一个函数,也可以达到装饰器函数的效果。

  

classlogging(object):

  def__init__(self,func):

  self.func=func

  

  def__call__(self,*args,**kwargs):

  print"[DEBUG]:enterfunction{func}()".format(

  func=self.func.__name__)

  returnself.func(*args,**kwargs)

  @logging

  defsay(something):

  print"say{}!".format(something)

带参数的类装饰器

  如果需要通过类形式实现带参数的装饰器,那么会比前面的例子稍微复杂一点。那么在构造函数里接受的就不是一个函数,而是传入的参数。通过类把这些参数保存起来。

  然后在重载__call__方法是就需要接受一个函数并返回一个函数。

  

classlogging(object):

  def__init__(self,level='INFO'):

  self.level=level

  

  def__call__(self,func):#接受函数

  defwrapper(*args,**kwargs):

  print"[{level}]:enterfunction{func}()".format(

  level=self.level,

  func=func.__name__)

  func(*args,**kwargs)

  returnwrapper#返回函数

  

  @logging(level='INFO')

  defsay(something):

  print"say{}!".format(something)

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: