Python装饰器的使用方法和示例:为函数增加额外功能
Python装饰器是一种处理函数的高级方法,它允许在不改变函数代码的情况下为函数添加额外的功能。在实际开发中,我们经常需要为函数添加类似于日志记录、性能统计、缓存等功能,使用装饰器可以使这些功能与原始函数解耦,并且可以重用装饰器,使代码更加简洁。本文将介绍Python装饰器的使用方法和示例。
一、装饰器的基本用法
装饰器是一个函数,它接受一个函数作为参数,并返回新的函数。新函数可以调用原始函数,并添加额外的操作。以下是一个简单的装饰器示例:
def my_decorator(func):
def wrapper():
print("wrapper start...")
func()
print("wrapper end...")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
输出结果:
wrapper start... Hello! wrapper end...
在这个示例中,我们定义了一个名为my_decorator的装饰器函数,它接受一个函数作为参数。wrapper函数调用了原始函数func,并添加了额外的操作。在say_hello函数前面加上了@my_decorator,相当于将say_hello函数作为参数传递给my_decorator函数,并将返回的新函数赋值给say_hello变量。
二、装饰器的进阶用法
除了在函数前面使用@decorator语法糖,装饰器还可以在函数内部手动调用。这种用法和函数嵌套很像,可以增加装饰器的灵活性和可重用性。以下是一个示例:
def my_decorator(func):
def wrapper():
print("wrapper start...")
func()
print("wrapper end...")
return wrapper
def say_hello():
print("Hello!")
decorated_say_hello = my_decorator(say_hello)
decorated_say_hello()
输出结果和前面的示例一样:
wrapper start... Hello! wrapper end...
在这个示例中,我们手动调用了my_decorator函数,并将原始函数say_hello作为参数传递进去,最后将返回的新函数赋值给decorated_say_hello变量,然后调用这个新函数。
装饰器还可以接收参数,并传递给原始函数。以下是一个示例:
def repeat(num):
def my_decorator(func):
def wrapper():
for i in range(num):
func()
return wrapper
return my_decorator
@repeat(num=3)
def say_hello():
print("Hello!")
say_hello()
输出结果:
Hello! Hello! Hello!
在这个示例中,我们定义了一个名为repeat的装饰器,它接收一个参数num,表示重复调用原始函数多少次。my_decorator函数再次定义了一个wrapper函数,用于循环调用原始函数。在say_hello函数前面使用了@repeat(num=3),相当于将num=3作为参数传递给了repeat装饰器。
三、常见的装饰器应用
1. 记录日志
在实际开发中,我们常常需要记录函数的调用过程,以便后续的分析和排查。使用装饰器可以很方便地实现这个功能:
def log_execution(func):
def wrapper(*args, **kwargs):
print(f"{func.__name__} start...")
result = func(*args, **kwargs)
print(f"{func.__name__} end...")
return result
return wrapper
@log_execution
def say_hello():
print("Hello!")
say_hello()
输出结果:
say_hello start... Hello! say_hello end...
在这个示例中,我们定义了一个名为log_execution的装饰器函数,它接收一个函数作为参数。wrapper函数记录了原始函数的开始和结束时间,并在调用后返回原始函数的结果。在say_hello函数前面使用了@log_execution,相当于将say_hello函数作为参数传递给了log_execution装饰器。
2. 统计函数执行时间
除了记录函数的调用过程,我们还经常需要统计函数的执行时间。使用装饰器可以很方便地实现这个功能:
import time
def measure_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.3f}s")
return result
return wrapper
@measure_time
def count_sum(n):
return sum(range(n))
print(count_sum(1000000))
输出结果:
499999500000 count_sum took 0.031s
在这个示例中,我们定义了一个名为measure_time的装饰器函数,它接收一个函数作为参数。wrapper函数记录了原始函数的开始和结束时间,并在调用后输出函数的执行时间。在count_sum函数前面使用了@measure_time,相当于将count_sum函数作为参数传递给了measure_time装饰器。
3. 缓存函数
在一些计算密集型的函数中,我们可能会需要缓存计算结果,以避免重复计算浪费时间。使用装饰器可以很方便地实现这个功能:
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(30))
输出结果:
832040
在这个示例中,我们定义了一个名为memoize的装饰器函数,它接收一个函数作为参数。wrapper函数记录了原始函数的参数和返回值,以避免重复计算。在fib函数前面使用了@memoize,相当于将fib函数作为参数传递给了memoize装饰器。
四、总结
Python装饰器是一种处理函数的高级方法,它允许在不改变函数代码的情况下为函数添加额外的功能。在实际开发中,我们经常需要为函数添加类似于日志记录、性能统计、缓存等功能,使用装饰器可以使这些功能与原始函数解耦,并且可以重用装饰器,使代码更加简洁。本文介绍了装饰器的基本用法和进阶用法,并举了一些常见的装饰器应用示例。在使用装饰器时,需要理解装饰器函数的参数、返回值和作用范围,并了解装饰器的调用顺序和优先级。
