配图解释一下装饰器的实现过程(执行步骤和引用对象的变化)

开发中有个“开放封闭”原则。开放就是说,允许对功能进行添加,封闭是指不要去改动原有的代码,避免牵一发而动全身,影响到其他功能;

在python中,装饰器就能实现对函数的功能进行添加,而不需要修改到函数内部的代码
一开始直接看程序不太好理解,不过分析了解释器的执行过程和对象引用的变化之后,发现挺好理解的。

下图配合解释一下装饰器的实现过程(本文末尾把它改成了正规装饰器写法)

(蓝色箭头代表程序运行的步骤,黄色箭头是对象的引用指向变化,红色框代表解释器给各个对象分配的内存空间)
装饰器实现原理

为什么执行的步骤是按照蓝色箭头那样的呢?

别急,先不看蓝色箭头,我们先分析一下解释器执行过程中,对象引用的变化过程,看红色框和黄色箭头

python中,一切皆为对象

解释器打开程序后,从上往下分析:
1、先分配了一个内存空间给set_func函数对象,并在它内部存了一个func;
2、接着分配一个内存空间给test_1函数对象,并在它内部存储了一行print代码;
3、然后把test_1函数对象作为参数给到func,这时候func就指向了test_1的内存空间;
同时还使用了赋值语句,修改了test_1 的指向,让它指向了set_func函数。
4、最后一行代码调用了test_1函数对象,是程序执行的开始。

接下来我们要找一下调用了test_1,它会去哪里找到内容来执行
1、test_1是指向了set_func函数对象存储的空间,那就先到set_func函数内部寻找,
到了set_func里面,解释器看到了def call_func(),所以先给call_func函数对象分配一个内存空间,并且存储了2行执行代码print和一个func对象的调用命令。

2、set_func函数里面虽然有call_func函数,但它没有被调用,所以解释器直接找到了return,return这行执行代码把call_func函数对象作为返回值,所以其实test_1实际上调用的是call_func函数,所以解释器接下来会找到call_func函数里面,就执行了2行print代码,并且调用了func函数。

3、而func函数它因为之前已经更改了指向,改成了指向原先test_1存储的空间,那么又找到了test_1存储的1行执行代码,就执行了。

所以整个执行过程就是蓝色箭头表示那样。

有几点需要明确的是:
1、解释器在执行的过程中,遇到定义函数,我们可以理解为会先给这个函数分配一个内存空间,如果里面有执行的代码就先存放着,有人调用这个函数才找过来执行代码。

2、在解释器眼里,赋值语句其实代表的是指向。指向的如果是个不可变的对象(比如说字符串),那么就直接找到它的内存空间。如果是个可变的对象,那就继续找一下这个可变对象到底存储在哪里。(这个结合深拷贝和浅拷贝比较好理解)

3、test_1代表的是函数对象,而test_1()则意味着调用了这个函数对象;

4、调用了一个对象,解释器就会去到这个对象所指向的存储空间里去找一下有没有代码执行,有的话,就按顺序执行;

这就是装饰器的实现过程,整个过程中,test_1内部的代码没有修改过,但是调用它的结果却不一样了,所以装饰器的作用就是可以给函数添加功能,但不需要修改函数的内部。

实际上用装饰器,会这么写

def set_func(func):
    def call_func():
        print("-----这是权限验证1-----")
        print("-----这是权限验证2-----")
        func()
    return call_func

@set_func
def test_1():
    print("------test_1------")
    
test_1()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值