装饰器模式,装饰器python的通俗理解

  装饰器模式,装饰器python的通俗理解

  Yyds干货库存

  Decorator介绍了为什么decorator软件的设计要遵循开闭原则,即对扩展开放,对修改封闭。对扩展开放意味着当有新的需求或变化时,现有的代码可以被扩展以适应新的情况。封闭修改是指对象一旦被设计出来,就可以独立完成工作,不需要修改。

  软件中包含的所有函数的源代码和调用方法都应该避免被修改,否则一旦错误被改正,很有可能会产生连锁反应,最终导致程序的崩溃。对于在线软件,新的需求或变化层出不穷,所以我们必须为程序提供扩展的可能性,所以我们使用装饰器。

  什么是室内设计师?“装饰”是指给被装饰的对象添加新的功能,“实现”是指器具/工具。装饰者和被装饰的对象可以是任何可调用的对象。一般来说,装饰器的作用是在不修改被装饰对象的源代码和调用方式的情况下,给被装饰对象增加额外的功能。Decorators常用于有截止需求的场景,比如日志插入、性能测试、事务处理、缓存、权限检查等应用场景。装修工是解决这类问题的优秀设计。有了decorators,大量与函数本身无关的完全相同的代码可以被提取出来并重用。

  提示:可调用对象是函数、方法或类。

  decorator Decorators的实现函数可以分为无参数decorator和无参数decorator两种,两者实现原理相同,都是‘函数嵌套闭包函数对象’结合的产物。

  无参数装饰导入时间的实现

  定义索引():

  时间.睡眠(3)

  打印(“欢迎使用索引页”)

  返回200

  Index() #函数执行遵循不修改被修饰对象源代码的原则,我们想到的解决方案可能如下

  start_time=time.time()

  Index() #函数执行

  stop_time=time.time()

  打印(运行时间为%s %(停止时间-开始时间))

  考虑到可以统计其他函数的执行时间,我们把它做成一个单独的工具。函数体需要外部传入修饰函数进行调用,我们可以作为参数传入。

  Def le(func): #通过参数接收外部值

  start_time=time.time()

  res=le()

  stop_time=time.time()

  打印(运行时间为%s %(停止时间-开始时间))

  返回res,但是在这之后,函数的调用方法需要改为

  乐(指数)

  Le(其他函数)这违反了被修饰对象的调用模式不可修改的原则,所以我们改变了函数体的传值方式,也就是将值包装到函数中,如下所示

  定义定时器(功能):

  Def le(): #引用外部作用域的变量func

  start_time=time.time()

  res=func()

  stop_time=time.time()

  打印(运行时间为%s %(停止时间-开始时间))

  返回资源

  Return le可以在不修改修饰函数的源代码和调用方式的情况下,在修饰函数中增加计时的功能,但只需要提前执行一次timer传入修饰函数,并返回一个闭包函数le重新赋给变量名/函数名索引,如下

  索引=计时器(索引)

  Index()到目前为止,我们已经实现了一个无参数装饰定时器,它可以在不修改其源代码和调用方式的情况下,向装饰对象索引添加新的函数。但是我们忽略了,如果修饰函数是参数函数,会抛出异常。

  定义家庭(姓名):

  时间.睡眠(5)

  打印(“欢迎来到主页”,姓名)

  主页=计时器(主页)

  家(了)

  #抛出异常

  类型错误:wrapper()接受0个位置参数,但1wasgiven引发了异常,因为home(le le )调用的实际上是ler (le ),并且包装函数没有参数。包装函数接收的参数实际上是针对原始func的。为了满足装饰函数的参数的所有条件,使用args *kwargs组合(参见4.3节),因此装饰器的计时器修改如下

  ef定时器(功能):

  def le(*args,**kwargs):

  start_time=time.time()

  res=func(*args,**kwargs)

  stop_time=time.time()

  打印(运行时间为%s %(停止时间-开始时间))

  返回资源

  Return le在这一点上,我们可以用timer来修饰有参数或者没有参数的函数。但是,为了简洁优雅地使用decorator,Python提供了一种特殊的decorator语法来代替index=timer(index)的形式。您需要将@timer添加到装饰对象正上方的单独一行中。解释器解释@timer的时候会调用timer函数,它正下方的函数名会作为参数传入,然后返回的结果会重新赋给原来的。

  @timer # index=timer(索引)

  定义索引():

  时间.睡眠(3)

  打印(“欢迎使用索引页”)

  返回200

  @ timer # index=timer(home)def home(name):

  时间.睡眠(5)

  Print(欢迎来到主页,name)如果我们有多个装饰者,我们可以叠加多个。

  @deco3

  @deco2

  @deco1

  定义索引():

  在pass上叠加多个decorators并没有什么特别的。上面的代码语义如下:

  Index=deco3(deco2(deco1(index))参数化decorator的实现在了解了无参数decorator的实现原理之后,我们就可以实现另一个decorator来为被修饰的对象添加认证功能了。实现的基本形式如下

  def deco(功能):

  def wc(*args,**kwargs):

  编写基于文件的身份验证。如果认证通过,将执行res=func(*args,**kwargs)并返回res。

  返回wc如果要提供多种不同的认证方式供选择,从wc函数实现的角度重新编写如下即可

  def deco(功能):

  def wc(*args,**kwargs):

  if driver==file :

  编写基于文件的身份验证。如果认证通过,将执行res=func(*args,**kwargs)并返回res。

  elif driver==mysql :

  编写基于mysql的认证。如果认证通过,执行res=func(*args,**kwargs)并返回res。

  返回wc函数需要一个驱动参数,而函数deco和wc的参数都有自己特定的函数,不能用来接受其他类型的参数。可以在deco外面包装一层函数auth专门接受附加参数,这样就保证了无论auth函数中有多少层都可以被引用。

  定义验证(驱动程序):

  def deco(功能):

  ……

  在这一点上,我们已经实现了一个参数装饰器,它可以如下使用

  先调用auth_type(driver=file )得到@deco,这是一个闭包函数,

  包含对外部作用域名驱动程序的引用,并且@deco的语法意义与无参数修饰符的语法意义相同。

  @auth(driver=file )

  定义索引():

  及格

  @auth(driver=mysql )

  def home():

  Pass可以使用help(函数名)查看函数的文档注释,本质上是查看函数的doc属性,但是对于修饰函数,查看文档注释。

  @定时器

  定义家庭(姓名):

  主页功能

  :参数名称:字符串

  :返回:无

  时间.睡眠(5)

  打印(“欢迎来到主页”,姓名)

  打印(帮助(主页))

  打印结果:

  模块__main__中函数包装器的帮助:

  包装(*args,**kwargs)

  无一装修后,home=wc。看home.name,还可以发现home的函数名确实是wc。如果希望保留原始函数的文档和函数名属性,需要修改装饰器。

  定义定时器(功能):

  def wc(*args,**kwargs):

  start_time=time.time()

  res=func(*args,**kwargs)

  stop_time=time.time()

  打印(运行时间为%s %(停止时间-开始时间))

  返回资源

  包装纸。__doc__=func。__doc__

  包装纸。__name__=func。__姓名_ _

  返回厕所

  转载请联系作者获得授权,否则将追究法律责任。

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

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