装饰器的作用就是在不修改函数源代码和调用方式的基础上为函数添加新的功能(开放封闭原则:对扩展开放,对修改封闭)
举个例子
这是备份数据的一个功能
import time
def back_db():
print("Backup database")
time.sleep(3) # 代表备份所花费的时间
现在要求我们添加一个日志功能,计算出备份所用的时间
def timer(func): # 改变了调用方式
start = time.time()
func()
end = time.time()
print("备份数据库用了%s" % (end - start))
这样的确可以计算出所用的时间,但是这样的话就改变了原来函数的调用方式,会影响程序的运行,所以我们换一种方式
def timer(func):
# func = back_db
def inner():
start = time.time()
func() # 这里的函数其实就是咱们要装饰的函数
end = time.time()
print("备份数据库用了%s" % (end - start))
return inner
back_db = timer(back_db) # back_db不是原来的函数,而是timer返回的inner函数
back_db()
其实上边的就是一个装饰器,但是python装饰器里有自己固定的语法
装饰器的语法(@装饰器名)
1.先定义装饰器函数
2.在被装饰函数的上方@装饰器的名字
python解释器遇到@的时候,就会把下方@装饰器下方的函数当做参数传递给装饰器,并把结果重新命名给被装饰的函数
import time
def timer(func):
def inner():
start = time.time()
func()
end = time.time()
print("备份数据库用了%s" % (end - start))
return inner
@timer
def back_db():
print("Backup database")
time.sleep(3) # 代表备份所花费的时间
back_db()
如果被装饰的函数有返回值呢,我们这样做
def timer(func):
def inner():
start = time.time()
res = func() # 这里把返回值赋值给res
end = time.time()
print("备份数据库用了%s" % (end - start))
return res # 利用inner函数返回被装饰函数的返回值
return inner
如果被装饰的函数有参数需要传参呢,我们这样做
def timer(func):
def inner(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs) # 传到了原函数这里
end = time.time()
print("备份数据库用了%s" % (end - start))
return res
return inner