python函数装饰器详解,python装饰器获取被装饰函数的参数

  python函数装饰器详解,python装饰器获取被装饰函数的参数

  装饰包装纸

  装饰品的功能

  装饰器用于向现有函数或对象添加其他函数。

  Decorators本质上是Python函数,其他函数可以添加到其他函数中,而无需更改代码。装饰器的返回值也是一个函数对象。通常用于有严格要求的场景,如日志插入、性能测试、事务处理、缓存和权限检查。Decorator是解决这个问题的优秀设计。有了decorator,很多类似的与函数本身无关的代码都可以画出来,重用。

  无参数装饰器

  调试(功能):

  defwrapper(:

  打印((调试) :输入{ }))。格式)func。__name_))

  返回函数()

  返回包装

  @调试

  def say_hello():

  打印(“你好!”)

  说你好()

  [调试]:输入say_hello()

  你好!

  把@debug放在say_hello()之前就大功告成了。

  say_hello=debug(say_hello))。

  Debug))是一个返回包装函数的decorator,所以原来的say_hello))仍然存在。但由于当前同名的now变量指向新函数,调用say_hello)会执行新函数(即debug)(函数返回的包装器)。

  可变参数装饰器

  调试(功能):

  EFwrapper(*Args,**kwargs)):

  打印((调试) :输入{ }))。格式)func。__name_))

  returnfunc(*Args,**kwargs)))))))))return func(* Args,* * kwargs))

  返回包装

  @调试

  defsay_Hello(名字什么的) :

  打印(你好!{}{}.格式(名字什么的) )

  说你好(罗征,.) )。

  [调试]:输入say_hello()

  你好!罗征。

  Python提供了变量参数*args和关键字参数**kwargs。有了这两个参数,装饰器可以用于任何目标函数。

  高级装饰工

  带参数的装饰器

  假设前面提到的decorator必须执行的函数不仅在进入某个函数后发出一条log消息,还需要指定log的级别。装修工就是这种情况。

  Eflogging(级别):

  efwrapper(func):

  definer _ wrapper(* Args,**kwargs):

  print([{ level }]:enter func(func)))。格式(

  水平=水平,

  函数=函数。__name__))

  returnfunc(*Args,**kwargs)))))))))return func(* Args,* * kwargs))

  返回内部包装

  返回包装

  @logging(level=info ).

  定义(某事) :

  打印(说)!格式(东西) )

  # @如果没有使用语法,它与

  #say=logging(level=info ) (say)).

  @logging(level=debug ).

  默认(某事):

  打印( do {}。。格式)(什么的))

  if __name__==__main__ :

  说(你好).

  我的工作)。

  【信息】:企业功能存储(

  打个招呼!

  [调试]:输入函数do(

  做我的工作。

  如果你遇到一个带参数的decorator的函数,比如@ logging (level= debug),它其实就是一个函数,会立即执行。如果这个函数返回的结果是decorator,那就没问题了。让我们仔细看看。

  基于类实现的装饰器

  装饰函数实际上是一个接口约束,它必须接受一个可调用对象作为参数,并返回一个可调用对象。在Python中,可调用对象通常是函数,但也有例外。只要对象是重载的_ _

  调用__()方法,那么这个对象是可调用的。重载__call__ magic方法一般会改变一个对象的内部行为,这样一个类对象就有了被调用的行为。

  类测试():

  def __call__(self):

  打印“打电话给我!”

  t=测试()

  打电话给我

  Decorator要求接受一个可调用对象并返回一个可调用对象(不太严格,见后面)。那么用类来实现也是可以的。我们可以让类的构造函数__init__()接受一个函数,然后重载__call__()返回一个函数,也可以达到装饰函数的效果。

  类日志记录(对象):

  def __init__(self,func):

  self.func=func

  def __call__(self,*args,**kwargs):

  print([DEBUG]:输入函数{func}()。格式(

  func=self.func.__name__))

  返回self.func(*args,**kwargs)

  @日志记录

  def说(某事):

  打印(说{} )。格式(东西))

  说(‘爱你。’)

  [调试]:输入函数say()

  说爱你。

  带参数的类装饰器

  类日志记录(对象):

  def __init__(self,level=INFO ):

  自我水平=水平

  def __call__(self,func): #接受函数

  极好的包装(*args,**kwargs):

  打印([{level}]:输入函数{func}() .格式(

  级别=自我级别,

  函数=函数. __姓名_ _))

  func(*args,**kwargs)

  退货包装#返回函数

  @日志记录(级别=信息)

  极好的说(某事):

  打印(说{} )。格式(东西))

  说(爱你。)

  打印(说__name__) #包装器

  内置装饰器@属性

  进行类属性读写的限制,Python基础(十二)—面向对象拾遗(插槽,@属性,)枚举类、元类)有讲解到。

  装饰器的注意事项

  不确定的代码执行顺序

  最好不要在装饰器函数之外添加逻辑功能,否则这个装饰器就不受你控制了。

  def html_tags(tag_name):

  打印(开始外部函数。)

  def wrapper_(func):

  打印(内部包装函数的开始)

  极好的包装(*args,**kwargs):

  content=func(*args,**kwargs)

  打印(“{content}{tag}”).格式(tag=tag_name,content=content))

  打印(内部包装函数结束)

  返回包装

  打印("外部函数结束")

  返回包装_

  @html_tags(b )

  def hello(name=Toby ):

  回复"你好{}!"。格式(名称)

  你好()

  你好()

  开始外部函数。

  外部函数结束

  内部包装函数的开始。

  内部包装函数的结尾。

  你好托比。

  你好托比。

  functools.wraps

  上面的一个例子:

  打印(说. name_) #包装器

  这是因为@等同于这样的写法:

  说=记录(说)

  记录其实返回的函数名字刚好是包装,那么上面的这个语句刚好就是把这个结果赋值给说,说的__姓名_ _自然也就是包装材料了,不仅仅是姓名,其他属性也都是来自包装,比如文档,来源等等。

  使用标准库里的functools.wraps,可以基本解决这个问题。

  从函数工具导入包装

  导入日期时间

  定义日志记录(函数):

  @wraps(func)

  极好的包装(*args,**kwargs):

  在函数前打印日志。

  打印([调试] {}:输入{}()。format(datetime.now()、func .__name__))

  return func(*args,**kwargs)

  返回包装

  @日志记录

  极好的说(某事):

  说点什么

  打印(说{}!。格式(东西))

  打印(说__name__) #说

  打印(说. doc__) #说点什么

  多层装饰器

  使用场景较小,可以参考以下代码或文章:Python装饰器执行顺序迷思。

  定义一个(函数):

  打印(- 1 -)

  def two():

  打印(- 2 -)

  函数()

  返回二

  定义一个(函数):

  打印(- a -)

  定义b():

  打印(- b - )

  函数()

  返回b

  @一个

  @a

  极好的演示():

  打印(- 3 -)

  演示()

  -一个-

  - 1 -

  - 2 -

  - b -

  - 3 -

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

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