浅谈python装饰器
概念
基本概念
python装饰器是一种用于拓展原有函数功能的一种函数。
功能
python装饰器的返回值也是一个函数,它可以提取大量函数中与本身无关的类似代码,从而实现代码复用,
而且还能将函数和类的功能扩充,实现被装饰对象的功能扩展。
应用场景
- 插入日志
- 性能测试
- 事务处理
- 权限校验
- 缓存
闭包与装饰器
闭包:在函数中嵌套一个函数,并且引用外部函数的变量。
def outer(x):
def inner(y):
return x + y
return inner
print(outer(1)(2))
------------------
>>>3
装饰器实际上是闭包的一种应用
装饰器就是对函数(方法)或者类的功能进行扩充,然后将扩充的方法或者类再返回。
装饰器的编写与使用
无参数的装饰器
编写一个统计函数运行花费的时间的装饰器如下
def cost_time(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print(f'---总共花了{round(end_time - start_time, 2)}秒---')
return wrapper
被装饰的函数如下
@cost_time
def sleeping():
for i in range(3):
s = random.randint(1, 4)
print(f'sleeping {s} seconds...')
time.sleep(s)
sleeping()
执行的结果
sleeping 2 seconds...
sleeping 1 seconds...
sleeping 3 seconds...
---总共花了6.0秒---
带参数的装饰器
依然是时间装饰器,修改上面的代码如下
def cost_time(parameter):
def cost_time_inner(func):
def wrapper(*args, **kwargs):
print(parameter) # 装饰器的参数
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print(f'---总共花了{round(end_time - start_time, 2)}秒---')
return wrapper
return cost_time_inner
被装饰的函数如下
@cost_time('---开始计时---')
def sleeping():
for i in range(3):
s = random.randint(1, 4)
print(f'sleeping {s} seconds...')
time.sleep(s)
结果如下
---开始计时---
sleeping 4 seconds...
sleeping 3 seconds...
sleeping 1 seconds...
---总共花了8.0秒---
相比上面的无参数装饰器多输出一句“开始计时”的话,这句话就是装饰器传递的参数。
类装饰器
装饰器除了可以用函数写,也可以用类来写,其用法与函数装饰器没有太大区别,实质上是用了类方法中的call方法来实现类的直接调用。
我们同样编写一个统计时间的类装饰器
class CostTime:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
start_time = time.time()
self.func()
end_time = time.time()
print(f'---总共花了{round(end_time - start_time, 2)}秒---')
被装饰的函数如下
@CostTime
def sleeping():
for i in range(3):
s = random.randint(1, 4)
print(f'sleeping {s}...')
time.sleep(s)
结果如下
sleeping 2...
sleeping 1...
sleeping 3...
---总共花了6.0秒---
可以看到,运行的过程和结果都跟无参数的装饰器差不多。同样类装饰器也可以带有参数,有兴趣的小伙伴可以自己尝试一下。
总结
好了,以上就是装饰器的一些概念和大概用法,想深入了解装饰器的话还是需要在平常多练习和应用中体会。