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

看了“大道曙光”的《探究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 的属性还是原来属性。

时间: 2024-08-27 15:14:34

自己编写一个装饰器中的装饰器函数的相关文章

python 一个.py文件如何调用另一个.py文件中的类和函数

原文地址https://blog.csdn.net/winycg/article/details/78512300 在同一个文件夹下 调用函数: 原文地址:https://www.cnblogs.com/111testing/p/9343182.html

基于OpenGL编写一个简易的2D渲染框架-07 鼠标事件和键盘事件

这次为程序添加鼠标事件和键盘事件 当检测到鼠标事件和键盘事件的信息时,捕获其信息并将信息传送到需要信息的对象处理.为此,需要一个可以分派信息的对象,这个对象能够正确的把信息交到正确的对象. 实现思路: 要实现以上的功能,需要几个对象: 事件分派器:EventDispatcher,负责将 BaseEvent 分派给 EventListener 对象 事件监听器:EventListener,这只是一个接口类,接受 BaseEvent 的对象,真正的处理在它的子类中实现 事件:BaseEvent,储存

c#中的字符串查找函数

indexOf()方法,查找某字符串在一个字符串内的位置,没有则返回-1string aa="abcdef";int a=aa.indexOf("bc");//a会等于1int b=aa.indexOf("a");//b会等于0int c=aa.indexOf("g");c会等于-1所以你只要判断返回出来的int值是不是小于0就知道这个字符串里有没有包含指定的另一个字符串 c#中的字符串查找函数,布布扣,bubuko.com

调用其他VBA工程中的过程和函数以及API函数

Excel VBA中,同一个应用程序下面包括多个工作簿,每个工作簿都有自己独立的VBAProject 在同一个VBA工程中,使用Call即可调用其他模块中的过程和函数,例如: Call Module2.Proc2 要注意:Call后面必须书写模块名或过程名,而不是双引号包起来的字符串. 当然也可以使用Excel的Application.Run “Module2.Proc2”调用另一个模块中的过程. 如果要调用另一个VBA工程中的过程和函数,Call就不好使了,需要使用Run,只不过要在模块前面加

浅显易懂的谈一谈python中的装饰器!!

hello大家好~~我是稀里糊涂林老冷,一天天稀里糊涂的. 前一段时间学习了装饰器,觉着这东西好高大上哇靠!!哈哈,一定要总结一下,方便以后自己查阅,也希望帮助其他伙伴们共同进步! 装饰器: 大家可以这样理解,装饰器是运用闭包的基本原理,对一个目标函数进行装饰.即是在执行一个目标函数之前.之后执行一些特定的事情. 学习装饰器一定要有闭包的基础知识,如果对闭包不是特别理解的话,可以参考我之前的博文http://www.cnblogs.com/Lin-Yi/p/7305364.html,也可以学习其

理解Python中的装饰器

文章先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: @makebold @makeitalic def say(): return "Hello" 打印出如下的输出: <b><i>Hello<i></b> 你会怎么做?最后给出的答案是: def makebold(fn): def wrapped(): return "<b>" + fn() + "</b>&q

python_如何修改装饰器中参数?

案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改timeout的值 如何解决这个问题? 定义一个装饰器,计算函数执行时间,并与timeout比较,当大于timeout时候,通过logging模块打印出日志信息 在包裹函数中添加一个函数,通过这个函数来修改timeout变量 在python3中用nonlocal来声明嵌套作用域中的变量引用,在pyth

@修饰符--python中的装饰器

http://blog.csdn.net/shangzhihaohao/article/details/6928808 装饰器模式可以在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职责,也能够处理那些可以撤销的职责.经常用于日志记录.性能测试等场合. 想象一下这个很常见的场景,你写了一个方法只提供给以登陆的用户访问(事实上我也是通过django的@login_required才了解到@修饰符的),你可以写以下代码: 这当然没什么问题,但是你又写了一个方法B,也要求只有登录用户可以访问

Python 中实现装饰器时使用 @functools.wraps 的理由

Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下--比如测试时--会导致一些问题.Python 通过 functool.wraps 为我们解决了这个问题:在编写装饰器时,在实现前加入 @functools.wraps(func) 可以保证装饰器不会对被装饰函数造成影响.比如,在 Flask 中,我们要自己重写 login_required 装饰器,但不想影响被装饰器装饰的方法,则 login_req