本文实例讲述了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函数装饰器原理与用法详解