要学习装饰器,首先要知道闭包的东西。不过这里不再说闭包的东西了。
我们假设一个场景:假如在公司有多个开发部门,A、B....。现在A部门开发出了一个功能,然后其他部门去调用A部门开发的功能。
比如: 如下f1、f2...,是由A部门来开发,然后其他部门使用。
def f1():print('f1')def f2():print("f2")...
然后有一天根据业务需要,需要在每个方法添加验证,也就是在执行功能前进行身份验证。
这个时候想必大家心里也都有方法。
比如 在f1 函数里面直接修改该代码加上验证。或者把验证方法提取出来,封装成哥函数。在调用f1之前先调用验证方法。如果用这两方法来修改的话,那么在其他部门调用的时候也需要修改调用方法。
def f1():#验证print('f1')
上面的两种方法中虽然能实现要求,但是写代码要遵循 开放封闭 原则,虽然在这个原则是⽤的⾯向对象开发,但是也适⽤于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展。
我再说一种用闭包实现的方法。
def w1(fn):def inner():print("验证中---")fn()return innerdef f1():print("f1")f1 = w1(f1)
# 调用的时候也是使用 f1()
说一下这个实现原理。
w1函数是要验证的代码,Python在解释的时候从上到下扫描,然后开辟了两个内存块,并且有两个变量 w1和f1分别指向对应的内存块。(如上图A所示)
在执行到 f1 = w1(f1) 的时候,w1函数里面还有个函数的定义,那么在 w1里面开辟一个内存(上图右面w1里面蓝色的框),并且里面有个变量f1。这个时候 w1(f1) 执行完后返回了inner函数的地址,也就是上图右边蓝色框的地址,并且把f1函数的地址指向了蓝色框。
所以根据上面的代码在执行 f1() 的时候 首先执行f1新指向的蓝色框,然后再执行蓝色框里面指向的旧f1的代码。
这样就能达到在f1里面加上新的代码了。其实这种方法就是闭包实现的,那么其实还有其他方法,也就是要说的装饰器,首先开一下 用装饰器怎么实现。
def w1(func):print("----------w1----------")def inner():print("inner")func()return inner@w1
def f1():print("f1")print("执行-------")
f1()
只需要在 f1函数定义前面加上 @w1 就行了。这就是装饰器!