从第2和第3次调用myfunc函数来看,并没有实现每次调用都返回第1次调用的效果,那么我们要实现每次调用都带有附加功能的效果,我们后面会=逐步实现。
第三步:使用@符号来装饰函数
# -*- coding:utf-8 -*-
'''示例3:使用@符号装饰函数,相当于"myfunc = deco(myfunc)",但发现新函数只在第一次被调用,且原函数多调用了一次。等价于第二步程序 '''
def deco(func):
print ("before myfunc() called.")
func()
print ("after myfunc() called.")
return func
@deco
def myfunc():
print ("myfunc()called.")
myfunc()
myfunc()
#执行结果:
before myfunc() called.
myfunc()called.
after myfunc() called.
myfunc()called.
myfunc()called.
第四步:使用内嵌包装函数来确保每次新函数都被调用
# -*- coding:utf-8 -*-
'''示例4: 使用内嵌包装函数来确保每次新函数都被调用,内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''
def deco(func):
def _deco():
print ("before myfunc() called.")
func()
print ("after myfunc() called.")
# 不需要返回func,实际上应返回原函数的返回值
return _deco
@deco
def myfunc():
print ("myfunc() called.")
return 'ok'
myfunc()
myfunc()
执行结果:
before myfunc() called.
myfunc() called.
after myfunc() called.
before myfunc() called.
myfunc() called.
after myfunc() called.
上面是实现了1个函数使用装饰器的例子,下面演示2个函数分别使用装饰器的实例:
# -*- coding:utf-8 -*-
'''增加打印函数执行时间功能,分别统计两个函数的执行效率 '''
import time
def deco(func):
def _deco():
start_time=time.time()
func()
end_time=time.time()
print("执行总耗时:",end_time-start_time)
return _deco
@deco
def myfunc():
print (" myfunc() called.")
time.sleep(1)
return 'true'
@deco
def youyfunc():
print (" youyfunc() called.")
time.sleep(2)
return 'true'
myfunc()
print ('*'*20)
youyfunc()
#结果:
#myfunc() called.
#执行总耗时: 1.0080790519714355
#********************
# youyfunc() called.
#执行总耗时: 2.0119848251342773
#执行过程解析:
执行myfunc()等价于执行deco(myfunc)()
#首先myfunc函数作为参数传递给了deco()函数,形参func被替换为实参myfunc,deco()函数开始顺序执行_deco()函数,
#先调用了myfunc()函数,开始执行myfunc函数,打印执行总耗时,最后返回_deco()函数对象。
说明:使用装饰器的函数之间变量不会互相影响,等于每次调用都会重新生成一个_deco函数。
第五步:实现对带参数的函数进行装饰
# -*- coding:utf-8 -*-
''' 内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象 '''
def deco(func):
def _deco(a, b):
print ("before myfunc() called.")
ret = func(a, b)
print ("after myfunc() called. result: %s" % ret)
return ret
return _deco
@deco
def myfunc(a, b):
print ("myfunc(%s,%s) called."%(a, b))
return a + b
myfunc(1, 2) #使用print (myfunc(1, 2)) 查看return ret 的结果
myfunc(3, 4)