Python函数装饰器原理与用法详解

  

本文实例讲述了Python函数装饰器原理与用法。分享给大家供大家参考,具体如下:

  

装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志,性能测试,事务处理,缓存,权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

  

严格来说,装饰器只是语法糖,装饰器是可调用的对象,可以像常规的可调用对象那样调用,特殊的地方是装饰器的参数是一个函数

  
  

现在有一个新的需求,希望可以记录下函数的执行时间,于是在代码中添加日志代码:

           导入的时间   #遵守开放封闭原则   def foo ():   开始=time.time ()   #打印(start) # 1504698634.0291758从1970年1月1号到现在的秒数,那年Unix诞生   time . sleep (3)   结束=time.time ()   打印('花% s ' %(结束-开始))   foo ()      之前      

栏(),bar2()也有类似的需求,怎么做?再在酒吧函数里调用时间函数?这样就造成大量雷同的代码,为了减少重复写代码,我们可以这样做,重新定义一个函数:专门设定时间:

        导入的时间   def show_time(函数):   start_time=time.time ()   函数()   end_time=time.time ()   打印(花% s的% (end_time-start_time))   def foo ():   打印(“你好foo”)   time . sleep (3)   show_time (foo)      之前      

但是这样的话,你基础平台的函数修改了名字,容易被业务线的人投诉的,因为我们每次都要将一个函数作为参数传递给show_time函数。而且这种方式已经破坏了原有的代码逻辑结构,之前执行业务逻辑时,执行运行foo(),但是现在不得不改成show_time (foo)。那么有没有更好的方式的呢?当然有,答案就是装饰器。

        def show_time (f):   def内部():   开始=time.time ()   f ()   结束=time.time ()   打印('花% s ' %(结束-开始))   回归内心的   @show_time # foo=show_time (f)   def foo ():   打印(“foo…”)   time . sleep (1)   foo ()   def bar ():   打印(“酒吧…”)   time . sleep (2)   酒吧()      之前      

输出结果:

  
  

foo……
  花1.0005607604980469
  酒吧…

     

函数show_time就是装饰器,它把真正的业务方法f包裹在函数里面,看起来像foo被上下时间函数装饰了。在这个例子中,函数进入和退出时,被称为一个横切面(方面),这种编程方式被称为面向切面的编程(面向方面编程)。

  

@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作

  

装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。

  

        def装修(函数):   打印(跑装修,函数)   def decorate_inner ():   打印(“运行decorate_inner函数”)   返回函数()   返回decorate_inner   @decorate   def func_1 ():   打印(“运行func_1”)   if __name__==癬_main__”:   打印(func_1)   #装修运行& lt;函数func_1 0 x000001904743dea0>   # & lt;功能布置灵活;locals> .decorate_inner 0 x000001904743df28>   func_1 ()   # decorate_inner运行函数   #运行func_1      之前      

        def装修(函数):   def decorate_inner (* args, * * kwargs):   print(类型(args)、类型(kwargs))   打印(args, args, kwargs, kwargs)   返回func (* args, * * kwargs)   返回decorate_inner   @decorate   def func_1 (* args, * * kwargs):   print (args, kwargs)   if __name__==癬_main__”:   func_1 (' 1 ', ' 2 ', ' 3 ', para_1=' 1 ', para_2=' 2 ', para_3=' 3 ')   #返回结果   # & lt;类的元组比;& lt;类dict的祝辞   # args (' 1 ', ' 2 ', ' 3 ') kwargs {“para_1”:“1”,“para_2”:“2”,“para_3”:“3”}   # (' 1 ',' 2 ',' 3 '){' para_1 ': ' 1 ', ' para_2 ': ' 2 ', ' para_3 ': ' 3 '}      

Python函数装饰器原理与用法详解