复习基础----装饰器

def f():
     print('2018-06-04)
#要求在每次调用f的时,打印‘2018-06-04’前打印一句‘开始’,之后打印一句‘结束’

在这里我们有两种方法:
1,直接更改原函数代码:简单粗暴(野蛮人使用的方法)
2,使用函数装饰器(文明人使用的方法)

1,什么是装饰器:

        是用来扩展被装饰对象功能的方法,在不改变原对象的代码前提下。

解决的方法:

      第一步:定义一个装饰器

def    wrapper(func):

         def   inner ():

                 print (‘开始’)

                 ret=func ()

                 print    ('结束‘)

                 return   ret

         return    inner

       第二步:为被装饰对象加上装饰器

@wrapper

def  f ():

       print ('2018-06-04')

 

在调用f函数时会首先去执行装饰器代码。

 

二,当遇到两个装饰器或多个装饰器时的执行顺序:

例:

def makeBold(fun):
    print('----a----')
    def inner():
        print('----1----')
        return '<b>' + fun() + '</b>'
    return inner

def makeItalic(fun):
    print('----b----')
    def inner():
        print('----2----')
        return '<i>' + fun() + '</i>'
    return inner

@makeBold
@makeItalic
def test():
    print('----c----')
    print('----3----')
    return 'hello python decorator'

ret = test()
print(ret)

输出结果为:

----b----
----a----
----1----
----2----
----c----
----3---- <b><i>hello python decorator</i></b>

 

可以发现,先用第二个装饰器(makeItalic)进行装饰,接着再用第一个装饰器(makeBold)进行装饰,而在调用过程中,先执行第一个装饰器(makeBold),接着再执行第二个装饰器(makeItalic)。

 

这里我们可以分两步来分析:

  1. 装饰时机 通过上面装饰时机的介绍,我们可以知道,在执行到@makeBold的时候,需要对下面的函数进行装饰,此时解释器继续往下走,发现并不是一个函数名,而又是一个装饰器,这时候,@makeBold装饰器暂停执行,而接着执行接下来的装饰器@makeItalic,接着把test函数名传入装饰器函数,从而打印’b’,在makeItalic装饰完后,此时的test指向makeItalic的inner函数地址,这时候有返回来执行@makeBold,接着把新test传入makeBold装饰器函数中,因此打印了’a’。
  2. 在调用test函数的时候,根据上述分析,此时test指向makeBold.inner函数,因此会先打印‘1‘,接下来,在调用fun()的时候,其实是调用的makeItalic.inner()函数,所以打印‘2‘,在makeItalic.inner中,调用的fun其实才是我们最原声的test函数,所以打印原test函数中的‘c‘,‘3‘,所以在一层层调完之后,打印的结果为<b><i>hello python decorator</i></b> 。

 

posted @ 2018-06-04 22:05  鲁之敬  阅读(89)  评论(0编辑  收藏  举报