装饰器详解
闭包
要想理解装饰器,首先得弄明白什么是闭包
函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包
def wrapper():
name = "ivy"
def inner():
print(name)
return inner
g = wrapper()
g()
根据上面的定义,wrapper函数里面定义了inner函数,inner函数里面使用了wrapper中的name变量。wrapper函数被调用后会返回内部的inner函数给g,当g再次被调用时,就会形成闭包。
为什么要使用装饰器
需求: 在不修改调用代码的情况下,计算一段业务代码的耗时
import time
def your_work():
start = time.time()
time.sleep(3) # 模仿业务耗时
end = time.time()
print(end - start)
your_work()
这里的time.sleep模拟任务的耗时,从这段代码中可以看到,计时和实际的业务代码写在一个函数中,可读性差,如果从面向对象的角度来看,这段代码违反了单一职责原则。
import time
def your_work():
time.sleep(3)
def spent_time(func):
start = time.time()
func()
end = time.time()
print(end - start)
spent_time(your_work)
将上面的代码修改,将计时和业务代码分开,虽然可读性高了,但是调用方式发生了改变,不符合需求。
这个时候,就要使用到装饰器了。
装饰器原理
import time
def wrapper(func):
print("wrapper....")
def inner():
start = time.time()
func()
end = time