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