装饰器是Python语言中一种特殊的语法结构,它在函数或者类的定义前面加上@decorator_name
的形式,用于修饰(decorate)函数或者类,以达到增强代码可读性、简化代码复杂度、提高代码复用性等目的。
装饰器的本质其实是一个函数,它接收一个函数作为参数并返回一个新函数。这个新函数通常会在接收参数之前先执行一些附加操作,可以是修改输入、输出参数,也可以是打印日志等等。简单来说,装饰器就是一种通过封装函数,实现对函数功能增强和拓展的方法。
在Python中,装饰器可以用于以下几种场景:
装饰器可以在执行函数前后打印日志,帮助我们调试程序。例如:
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling function {func.__name__}")
result = func(*args, **kwargs)
print(f"Function {func.__name__} returned: {result}")
return result
return wrapper
@log_decorator
def add(x, y):
return x + y
add(1, 2) # 执行结果:Calling function add; Function add returned: 3
装饰器可以用来计算函数执行时间,方便我们优化程序。例如:
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {(end_time - start_time)*1000:.2f}ms to execute")
return result
return wrapper
@timer_decorator
def add(x, y):
return x + y
add(1, 2) # 执行结果:Function add took 0.02ms to execute
装饰器可以在函数执行前进行用户权限和身份的验证,限制函数的调用。例如:
user_1 = {"id": 1, "name": "User 1", "is_admin": False}
user_2 = {"id": 2, "name": "User 2", "is_admin": True}
def admin_only(func):
def wrapper(user, *args, **kwargs):
if not user["is_admin"]:
raise Exception(f"User {user['name']} is not authorized to execute this function")
return func(user, *args, **kwargs)
return wrapper
@admin_only
def delete_user(user, user_id):
print(f"Deleting user {user_id}")
return True
delete_user(user_1, 1) # 执行结果:Exception: User User 1 is not authorized to execute this function
delete_user(user_2, 1) # 执行结果:Deleting user 1
装饰器可以将某个函数的计算结果缓存起来,在下一次调用时直接返回缓存值,以提高程序的运行效率。例如:
def cache_decorator(func):
cache = {}
def wrapper(*args, **kwargs):
key = (args, tuple(sorted(kwargs.items())))
if key in cache:
print(f"Returning cached result for {func.__name__}")
return cache[key]
result = func(*args, **kwargs)
cache[key] = result
return result
return wrapper
@cache_decorator
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
fib(10) # 执行结果:Returning cached result for fib; 55
上面只是几种装饰器的例子,实际上,装饰器还能用于其他更多的场景,如设置自动重试机制、线程池等等。值得一提的是,Python标准库中也有一些常用的装饰器,例如@property
、@staticmethod
、@classmethod
等等,它们能帮助我们更方便地编写类和方法。
最后需要注意的是,装饰器本身也需要遵守一定的规则,以保证它的正确性和可读性。例如,装饰器应该保留被装饰函数的元信息,可以使用functools.wraps
装饰器来达到这个目的。
总而言之,Python装饰器是一个强大而灵活的工具,通过合理使用装饰器可以让我们的程序更加简洁、优雅、易于维护。