1. 闭包函数
要想了解装饰器,首先要了解一个概念,闭包。
我们先来看看闭包函数。我们知道python是一种面向对象的编程语言,也就是说python中一切皆对象,所以我们在函数中定义函数是合法的行为
,我们管这种函数叫内嵌函数。这种函数只可以在外部函数的作用域内被正常调用
。
def outer(x):
print(f'x = {x}') # x = 6
def inner(y):
print(f'y = {y}') # y = 5
print(f'x + y = {x+y}') # x + y = 11
return x + y
return inner
outer(6)(5)
2. python装饰器
好了,我们现在对闭包有一定的了解了,下面再来看看装饰器。python装饰器本质上就是一个函数,它可以让其他函数在 不需要做任何代码变动的前提下增加额外的功能
,装饰器的返回值也是一个 函数对象(函数的指针)
。在这里插入代码片
2.1 函数装饰器
(1)函数的函数装饰器
下列功能为测试func函数的耗时程序,其中func可以为任意传入函数。为了测试hello函数的耗时,有两种做法,一种是将hello传入decorator函数中,另一种是将hello添加装饰器
。
- 普通函数调用实现
import time
def decorator(func):
print("1. start decorator!")
def wrapper(*args, **kwargs):
print("4. wrapper")
print(f"func name is : {func.__name__}") # 输出传入的func名字
start_time = time.time() #秒
func()
end_time = time.time()
print("7. time: ",end_time - start_time) # 测试耗时
print("2. end decorator!")
return wrapper
def hello():
print("5. hello")
time.sleep(1.3)
print("6. world")
if __name__ == '__main__':
print('*******开始main*********')
f = decorator(hello)
print("3. start wrapper!")
f()# 执行闭包函数,也就是wrapper
输出:
*******开始main*********
1. start decorator!
2. end decorator!
3. start wrapper!
4. wrapper
func name is : hello
5. hello
6. world
7. time: 1.301443338394165
- 装饰器实现
装饰器的实现方式,并不会对源程序做任何改变
,如下所示。
import time
def decorator(func):
print("1. start decorator!")
def wrapper(*args, **kwargs):
print("4. wrapper")
print(f"func name is : {func.__name__}") # 输出传入的func名字
start_time = time.time() #秒
func()
end_time = time.time()
print("7. time: ",end_time - start_time) # 测试耗时
print("2. end decorator!")
return wrapper
@decorator
def hello():
print("5. hello")
time.sleep(1.3)
print("6. world")
if __name__ == '__main__':
print('*******开始main*********')
hello()
输出:
1. start decorator!
2. end decorator!
*******开始main*********
4. wrapper
func name is : hello
5. hello
6. world
7. time: 1.3001999855041504
(2)类方法的函数装饰器
对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数 - me_instance就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。
import time
def decorator(func):
def wrapper(me_instance):
start_time = time.time()
func(me_instance)
end_time = time.time()
print(end_time - start_time)
return wrapper
class Method(object):
@decorator
def func(self):
time.sleep(0.8)
p1 = Method()
p1.func() # 函数调用
2.2 类装饰器
class Decorator(object):
def __init__(self, f):
self.f = f
def __call__(self):
print("decorator start")
self.f()
print("decorator end")
@Decorator
def func():
print("func")
f = func
print("start call!")
f()
输出:
start call!
decorator start
func
decorator end