一、介绍
装饰器(Decorators)是 Python 的一个重要部分。
Python装饰器可扩展和修改可调用对象的行为,而无需修改可调用对象本身。装饰器是装饰(或包装)其他功能并在包装的功能运行之前和之后执行代码的功能。让我们的代码更简短。
Python装饰器通常用于日志记录,性能测试,身份验证和授权,计时和缓存等。
python官网:链接
python教程:链接
Decorators:链接
二、装饰器用法
python提供了@符号作为装饰器的语法糖,使我们更方便的应用装饰函数。但使用语法糖要求装饰函数必须return一个函数对象。
2.1.不带@符号的Python装饰器
def a(func):
def wrapper():
print("11111")
func()
print("22222")
return wrapper
def b():
print("bbbbbbb")
#调用
func = a(b)
func()
这里a函数是一个装饰器,通过在输出中添加两行打印来装饰
2.2.带@符号的Python装饰器
def a(func):
def wrapper():
print("11111")
func()
print("22222")
return wrapper
@a
def b():
print("bbbbbbb")
#调用
b()
2. functools @wraps装饰器
应用装饰功能后,name,doc,和__module__原有功能的属性都将丢失。这使调试很麻烦。为了解决这个问题,我们可以使用functool’s @wraps装饰器。
#!/usr/bin/env python
from functools import wraps
def a(fun):
@wraps(fun)
def wrapper():
'''this is wrapper()'''
print("***************************")
fun()
print("***************************")
return wrapper
@a
def b():
'''this is b()'''
print("bbbb")
#调用
b()
print(b.__name__)
print(b.__doc__)
2.Python类装饰器
我们调用该update_wrapper()函数。它具有与@wraps装饰器相同的目的;即,它保留原始函数(name__或__doc)的元数据。我们保留对原始函数的引用并设置num_of_calls变量。
使用装饰器实现一个计数器功能
#!/usr/bin/env python
import functools
class CountCalls:
def __init__(self, fun):
functools.update_wrapper(self, fun)
self.fun = fun
self.num_of_calls = 0
def __call__(self, *args, **kwargs):
self.num_of_calls += 1
print(f"Call {self.num_of_calls} of {self.fun.__name__} fun")
return self.fun(*args, **kwargs)
@CountCalls
def hello():
print("Hello there!")
#调用
a = hello()
b = hello
print(b.num_of_calls)