Python装饰器是一个高级概念,它允许开发者在不改变函数源代码的情况下,增强函数的功能。简单来说,装饰器就是一个函数,它接受一个函数作为参数,并返回一个新的函数。
让我们从一个简单例子开始。假设我们有一个打印问候语的函数:
def greet():
print("Hello, world!")
现在,我们想要在每次调用这个函数时记录日志。传统的方法是修改函数内部,但这样做会破坏函数的纯洁性。装饰器提供了一种解决方案:
def log_decorator(func):
def wrapper():
print("Log: Function is being called.")
func()
print("Log: Function has been called.")
return wrapper
greet = log_decorator(greet)
在这个例子中,log_decorator
就是装饰器。它接收greet
函数作为参数,并返回一个新的函数wrapper
。当我们调用greet()
时,实际上是在调用wrapper()
,它会先打印日志,然后调用原始的greet
函数。
装饰器的强大之处在于它的灵活性和复用性。我们可以创建多个装饰器,用于不同的功能,如计时、缓存结果等。而且,装饰器可以堆叠使用,形成装饰器链。
例如,如果我们还想添加一个计时功能,可以这样做:
import time
def timer_decorator(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print(f"Execution time: {end_time - start_time} seconds")
return wrapper
greet = timer_decorator(greet)
这里,我们首先用timer_decorator
装饰了greet
函数,然后又用log_decorator
装饰了它。当我们调用greet()
时,两个装饰器都会被触发。
装饰器还可以接收参数,这使得它们更加灵活。带参数的装饰器需要使用嵌套函数和闭包的概念。下面是一个例子:
def repeat_decorator(times):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat_decorator(3)
def greet():
print("Hello, world!")
在这个例子中,repeat_decorator
是一个带参数的装饰器。它接收一个参数times
,然后返回一个装饰器decorator
。这个装饰器接收一个函数func
,然后返回一个新的函数wrapper
。wrapper
函数会重复调用func
多次。
最后,我们使用了@
语法糖来简化装饰器的调用。@repeat_decorator(3)
等同于greet = repeat_decorator(3)(greet)
。
通过这些例子,我们可以看到装饰器如何优雅地解决了函数增强的问题。它们不仅提高了代码的可读性和复用性,还避免了对原始函数的直接修改。在实际应用中,装饰器可以用于日志记录、性能测试、权限检查等多种场景。掌握装饰器的使用,将使你的Python技能更上一层楼。