当前位置: 首页 > 后端技术 > Python

浅谈python装饰器的实现原理

时间:2023-03-26 14:57:10 Python

1.装饰器刚开始学习装饰器的时候,会觉得抽象,生涩。其实装饰器就是为了增强一个对象的功能。下面详细说一下“增强”的实现原理。2.增强实现的原理其实原理就一句话:改变旧对象指向新函数wrapperdeflog(func):defwrapper(*args,**kw):print('call%s():'%func.__name__)returnfunc(*args,**kw)returnwrapper@logdefnow():print('2015-3-25')>>>现在()现在调用():2015-3-25以上是廖雪峰-python-decorator中的例子,这里做详细解释:python解释器在执行now()之前,首先加载环境,加载内存b中对应的程序。找到后,从最上面开始Next,先执行@log:now=log(now)我们仔细看看log(now)发生了什么,重点关注指向对象的变化1.首先解释器根据变量名log在内存中找到对应的变量2.now函数传递给log函数。重要的一点是此时参数func和now指向同一个对象,即内存中存储的```defnow():print('2015-3-25')```3.这时候解释器继续读程序,直到遇到return。这里需要注意的是,此时调用的是日志函数,此时并没有调用日志内部的包装函数(闭包),所以此时执行的是日志函数的返回语句`returnwrapper`。log函数将`wrapper`返回给c。log(now)返回包装器,然后将其分配给现在。关键是,now变量指向的对象从defnow():print('2015-3-25')变为defwrapper(*args,**kw):print('call%s():'%func.__name__)返回func(*args,**kw)d。abc结束后,解释器执行完@log,然后读取now()语句开始执行:1、此时now和wrapper指向同一个对象。这里我再说一件事。其实,如果这时候运行```>>>now.__name__'wrapper'```,如果想避免这种情况,可以使用@functools.wraps(func)2.我们继续执行,遇到`print('call%s():'%func.__name__)`,执行打印内容3.遇到`returnfunc(*args,**kw)`,记住,我们func指向的对象是谁上文提到的?4.调用func5。解释器找到func指向的程序,```defnow():print('2015-3-25')```6.执行`print('2015-3-25')`e。至此,now()的执行结束。根据abcd的描述,大家应该能看懂返回结果>>>now()callnow():2015-3-253.描述为了解释容易理解,请忽略不准确的地方上面的一些条款。本章内容不涉及装饰器“外部函数只执行一次”的知识点。这个知识点正好和装饰器实现单例模式有关,所以我打算放在那里,有兴趣的朋友可以看看。4.留个小问题给检查。为什么在now()的返回结果中调用now()而不是调用wrapper()?提示:答案在上面的解释中。