想再说一下装饰器的使用和原理。
之前已经说了装饰器的概念,和语法,这里想再进一步说一下几个装饰器的例子。
例子一:
def makBlod(fn):def wrappen():return "<b>" + fn() + "</b>"return wrappendef makItalic(fn):def wrappen():return "<i>" + fn() + "</i>"return wrappen@makBlod
def test1():return "hello world - 01"@makItalic
def test2():return "hello world - 02"@makBlod
@makItalic
def test3():return "hello world - 03"print(test1())
print(test2())
print(test3())
首先看到上面的例子的时候,函数 test1和test2的执行结果一看就了然于心,那么test3函数的执行结果真的是要好好想想解释器的原理了。先看结果。
<b>hello world - 01</b>
<i>hello world - 02</i>
<b><i>hello world - 03</i></b>
那么装饰器的原理到底是怎么样呢!比如 test3 这个函数被两个装饰器@makBlod和@makItalic 同时装饰了。那么在具体说明原理之前先说一下装饰器在装饰的时候是从下向上装饰的,看下面代码和执行结果。
def makBlod(fn):print("makBlod")def wrappen():return "<b>" + fn() + "</b>"return wrappendef makItalic(fn):print("makItalic")def wrappen():return "<i>" + fn() + "</i>"return wrappen@makBlod
@makItalic
def test3():return "hello world - 03"print(test3())
makItalic
makBlod
<b><i>hello world - 03</i></b>
在装饰器里面加了各加了一行代码,从代码的执行的结果可以看出,makItalic装饰器先执行了,然后才是上面makBlod装饰器执行。由此可得出,装饰器在装饰的时候是从下向上装饰的(也就是先@makItelic然后才是@makBlod )。
第一步:装饰 @makItali,看粉色的线段,这个时候全局下的变量test3指向了makItalic 函数里面函数 wrappen 的位置,也就是说此时,全局下的函数test3在执行的时候是执行 makItalic 里面的 wrappen函数,wrappen的test3函数就指向原来test3函数的指引位置。
第二部:装饰 @makBlod,看绿色的线段。因为第一步里面test3函数是 makItalic 里面的wrappen,所以在装饰的时候,穿进去局部变量函数test3应该是 makItalic 里面的wrappen(看绿色曲线所指引的位置),在makBlod函数装饰完成后,全部变量test3所指引的位置应该是 makBlod函数里面的wrappen局部函数。
上面两步装饰器的装饰工作完成,那么在调用的时候,test3() 。
1、makBlod函数里面的wrappen先执行。
2、makItalic函数里面的wrappen载执行。
3、最下面那个代码块再执行(就是原来全局下test3所指引的位置)
这个执行完后,return 出来的结果就构成了 <b><i>hello world - 03</i></b> 这样的结果。