python 装饰器作用,python装饰器--原来如此简单

  python 装饰器作用,python装饰器--原来如此简单

  在理解wrappers修饰符之前,您需要首先理解partial和update_wrapper函数。因为这两个函数是在wraps的代码中使用的。

  偏先说偏函数。在公式的叙述中,这个函数的语句如下。功能工具。部分(func,*args,**keywords).这样做的目的是返回分部对象,以便以func(*args,**kwargs)的形式调用func函数。如果其他位置参数(args)关键字参数(*kwargs)被传递给这个部分对象,它们也被传递给func函数。如果一个参数被多次传递,后面的值将覆盖前面的值。

  例如,下面的例子:

  FromfunctoolsImportPartialDefAdd(x:int,y:int): return x y#现在我们创建了一个新的函数add2,它只取一个整数参数,并将其与2addd2=partial相加。Y=2) add2(3)3) #这里显示如下,请参考。

  defpartial(func,*args,**keywords ) :defnewfunc ) *args,* * * f keywords(:new keywords=keywords . copy)* fargs,* new keywords(new func . func=funcnewfunc . args=argsnewfunc . keywords=keywordsreturnnewfuncdupdate _ wrap pped

  defupdate_wrapper(wrapper,wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER _ UPDATES)3360 updateawwrapperfunctiontolooklikethewrappedfunctionwrapperisthefunctiontobeupdatedwwrappedistheoriginalfunctionasigng signeddirectlyfromthewrappedfunctiontowrapperfunction(defaultstofunction . as ign mment updatedisatuplenamenget datewiththecorresponding attributefromthewrappedfu function(ols . WRAPPER _ UPDATES( for attrinassigned 3360 tryupdate)getattr)wrap at { })# issue # 174823360 update _ Ting ReturnTheWrapperThiScanbe _ sed adapt返回包装器用于从被修饰的函数(wrapped)中检索一些属性值,然后从3358www中提取出来。Sina.com/.

  为什么要这么做?让我们看看下面的例子。

  自定义装饰器v1首先我们来写一个自定义装饰器,它没有函数,只有一个文档字符串,如下图:

  def wrapper(f):def wrapper _ function(* args,* * kwargs): 这是修饰函数 return f(*args,* * kwargs)return wrapper _ function @ wrapper def wrapped(): 这是修饰函数 print (wrapped) print (wrapped。_ _ doc _ _) # output `这是修饰函数` print(wrapped。_ _ name _ _)# output ` wrapper_function 从上面的例子中我们可以看到,我本来想获取包装函数的文档字符串,但是它变成了wrapper_function的文档字符串,包装函数的名字变成了wrapper _ function函数的名字。这是因为将@wrapper修饰符添加到wrapped相当于执行wrapped=wrapper(wrapped)的一句话。执行该语句后,包装的函数成为wrapper_function函数。遇到这种情况我们该怎么办?首先我们可以在wrapper function中手动更改wrapper_function的__doc__和__name__属性,但是聪明的你一定想到了。我们可以直接使用update_wrapper函数来实现这个功能。

  自定义装饰器v2我们稍微修改了上面定义的装饰器,并添加了一个update _ wrapper(wrapper _ function,f)。

  From functools导入update _ wrapper def wrapper(F):def wrapper _ function(* args,* * kwargs): 这是修饰函数 return f(*args,* * kwargs)update _ wrapper(wrapper _ function,F) #添加了此语句return wrapper _ function @ wrapper def wrapped(): 这是修饰函数 print (wrapped) print (wrapped。_ _ doc _ _) # output `这是修饰函数` Print(wrapped。__name__)# output wrapped 此时,我们可以发现__doc__和_ _ name _ _属性已经按照我们的预期显示出来了。此外,update_wrapper函数还更改和更新了__module__和__dict__属性。

  包修饰器好吧,至此,我们已经了解了部分的和更新_包装这两个函数的功能,接下来我们翻出包修饰器的源码:

  WRAPPER _ ASSIGNMENTS=( _ _ module _ _ , __name__ , __qualname__ , __doc__ , _ _ annotations _ _ )WRAPPER _ UPDATES=( _ _ dict _ _ ,)def wrappers(wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER _ UPDATES): 装饰工厂将更新包装器()应用于包装函数,返回调用更新包装器()的装饰器,其中装饰函数作为包装器参数,包装()的参数作为其余参数。默认参数与更新包装器()相同。这是一个方便的函数,可以简化对更新包装器()应用部分()的过程。返回部分(update_wrapper,wrapped=wrapped,assigned=assigned,updated=updated)没错,就是这么的简单,只有这么一句,我们可以看出,包装函数其实就是一个修饰器版的更新_包装函数,它的功能和更新_包装是一模一样的。我们可以修改我们上面的自定义修饰器的例子,做出一个更方便阅读的版本。

  自定义修饰器v3从函数工具导入wrapps def wrapper(f):@ wrapps(f)def wrapper _ function(* args,**kwargs): 这个是修饰函数 return f(*args,* * kwargs)return wrapper _ function @ wrapper def wrapped(): 这个是被修饰的函数打印(换行)打印(换行. doc__) #输出`这个是被修饰的函数`打印(换行__name__) #输出`已包装至此,我想大家应该明白包这个修饰器的作用了吧,就是将被修饰的函数(wrapped)的一些属性值赋值给修饰器函数(wrapper),最终让属性的显示更符合我们的直觉。

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

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