自己编写一个装饰器中的装饰器函数

Posted 先完成一个小目标

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己编写一个装饰器中的装饰器函数相关的知识,希望对你有一定的参考价值。

看了“大道曙光”的《探究functools模块wraps装饰器的用途》的文章。基本上弄清了wraps的工作原理,为了检验一下自己理解的程度,于是动手写一个类似的 wraps函数,请大家指教。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#filename : mywrapper.py
#date: 2017-06-02
‘‘‘ wrapper function by my code.‘‘‘
import functools
import sys

WAPPER_ASSIGNMENTS = (‘__module__‘,‘__name__‘,‘__qualname__‘,
                       ‘__doc__‘,‘__annotations__‘)
WAPPER_UPDATES = (‘__dict__‘,)

def mywrapper_update(wrapper,
                      wrapped,
                      assigned = WAPPER_ASSIGNMENTS,
                      updated = WAPPER_UPDATES):

                     ‘‘‘ wrapper 闭合函数
                          wrapped 被调用函数‘‘‘
                      #将 WAPPER_ASSIGNMENT 元组中的属性 从被调用函数复制到闭合函数
                      for x in assigned:
                          try:
                              value = getattr(wrapped,x)
                          except:
                              pass
                          else:
                              setattr(wrapper,x,value)
                      # 从被调用函数字典内容更新到闭合函数
                      for x in updated:
                          getattr(wrapper,x).update(getattr(wrapped,x))

                     wrapper.__wrapped__ = wrapped   #被调用函数的原始保存,help(add.__wrapped__) 可测试对比
                      return wrapper

def mywraps(wrapped,
             assigned = WAPPER_ASSIGNMENTS,
             updated = WAPPER_UPDATES):
             def callf(func):
                 return mywrapper_update(func,wrapped,assigned,updated)
             return callf

                    

#================测试===================
debug_log = sys.stderr
def trace(func):
     if debug_log :
         @mywraps(func)             #把被调用函数当作装饰器函数的参数
         def callfile(*args,**kwargs): # callfile 成了装饰器函数的被调用函数   
             debug_log.write(‘function name:{}\n‘.format(func.__name__))
             debug_log.write(‘function args:{}\n‘.format(args))
             debug_log.write(‘callfile name:{}\n‘.format(callfile.__name__))
             res = func(*args,**kwargs)
             return res
         return callfile
     else:
         return func

@trace
def add(x,y):
     ‘‘‘ return x+y ‘‘‘
     return x+y

print add(5,6)
print ‘func name:‘,add.__name__
help (add)

help(add.__wrapped__)


#=========运行结果=====================

function name:add
function args:(5, 6)
callfile name:add
11
func name: add
Help on function add in module __main__:

add(*args, **kwargs)
     return x+y

Help on function add in module __main__:

add(x, y)
     return x+y

个人理解总结:mywraps 的作用就是装饰器中的装饰器,通过在装饰器中把func的一系列属性复制给callf,来达到在调用被装饰过的add函数时,add 的属性还是原来属性。

以上是关于自己编写一个装饰器中的装饰器函数的主要内容,如果未能解决你的问题,请参考以下文章

Python - 在装饰器中获取原始函数参数

python包装函数在装饰器中接受参数

如何在 Django 中编写自己的装饰器?

如何将装饰器中的变量传递给装饰函数中的函数参数?

装饰器

为啥 Angular AoT 不支持装饰器中的函数表达式?