关于装饰器:浅谈python装饰器的实现原理

一、装璜器
在初学装璜器的时候,会感觉形象生涩,其实装璜器就是对某个对象进行性能上的加强
上面具体讲一下 “加强” 的实现原理

二、加强的实现原理
其实原理就一句话:更改旧对象的指向,指向 结构的新的函数wrapper

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
@log
def now():
    print('2015-3-25')
>>> now()
call now():
2015-3-25

下面是拿廖雪峰-python-装璜器中的例子,在此做一个具体阐明:
a. python解释器在执行now()之前,首先加载环境,加载内存中对应的程序

b. 找到后,自上而下执行,于是先执行 @log
即执行: now = log(now)

咱们来具体看一下log(now)产生了什么,重点关注指向对象的变动
1、首先解释器依据变量名log,找到内存中对应的程序
2、now函数传入log函数,重点来了,参数func和now 此时指向同一个对象,即内存中存储的
```
def now():
    print('2015-3-25')
```
3、此时解释器持续向下读取程序,直到遇到return返回。这里要留神,
此时调用的是log函数,log外部的wrapper函数(闭包)此时并没有被调用,
所以此时执行log函数的return语句`return wrapper`
log函数将`wrapper`返回

c. log(now)返回wrapper,而后赋值给now,重点来了,now变量指向的对象从

def now():
    print('2015-3-25')

变为

def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)

d. abc完结后,解释器执行完@log,接下来读取到now()语句,开始执行:

1. 此时now曾经和wrapper指向同一个对象,这里多说一句,其实此时如果运行
    ```
    >>> now.__name__
    'wrapper'
    ```
如果想要防止这种状况,能够应用@functools.wraps(func)
2. 咱们继续执行,遇到`print('call %s():' % func.__name__)`,执行print内容
3. 遇到`return func(*args, **kw)`,还记得吗,下面咱们提到func指向的对象是谁?
4. 调用func
5. 解释器找到func指向的程序,
    ```
    def now():
        print('2015-3-25')
    ```

6. 执行 `print('2015-3-25')`

e. 至此,now()执行完结,依据abcd的阐明,大家应该能够了解返回的后果了

>>> now()
call now():
2015-3-25

三、阐明
为了解释的通俗易懂,请大家疏忽下面一些话术用语的不精确。
这章内容没有波及到装璜器的“外函数只执行一次”这一知识点,这个知识点正好和
装璜器实现单例模式 相干,所以打算放到那里讲,有趣味的敌人能够去看。

四、考查
留一个小问题,now()的返回后果中,
为什么是 call now() 而不是 call wrapper() ?

hint:答案就在下面的解说中。

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年50元

阿里云限时活动-2核2G-5M带宽-60G SSD-1000G月流量 ,特惠价99元/年(原价1234.2元/年,可以直接买3年),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据