Python装饰器初探:功能及应用示例
Python装饰器是一种方法,用于动态地修改或增强函数的功能。装饰器本身是一个函数,它接受一个函数对象作为参数,并返回一个新函数对象,可以用于替换或包装原始函数。在此方面,装饰器类似于函数式编程中的高阶函数,因为它们可以将函数作为参数。
Python装饰器有许多用途和应用示例。在本文中,我们将介绍一些常见的用例和作用。我们还将讨论如何编写自己的装饰器以及一些实际的例子。
功能及应用示例
1. 记录函数执行时间
在实际编程中,我们可能需要知道程序的执行时间。这就是一个很好的应用场景来使用装饰器。下面是一个简单的示例,我们使用装饰器来记录函数的执行时间:
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Function {func.__name__} took {end-start:.2f} seconds to execute")
return result
return wrapper
@timing_decorator
def example_function():
time.sleep(2)
example_function()
这里定义了一个装饰器timing_decorator,它会将被装饰函数的执行时间打印到控制台上。然后我们使用了装饰器来修饰一个简单的函数example_function(),这个函数只是简单的睡眠2秒钟并没有其他的操作。当我们运行程序时,控制台将输出以下内容:
Function example_function took 2.00 seconds to execute
此时我们就成功地记录了程序的执行时间。
2. 检查函数参数
另一个实际的例子是在函数调用之前检查函数参数的有效性。例如,我们可以创建一个装饰器,该装饰器检查一个函数的参数是否全部都是数字:
def verify_number_decorator(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, (int, float, complex)):
raise TypeError(f"Unexpected type: {type(arg)}, expected int, float, or complex")
return func(*args, **kwargs)
return wrapper
@verify_number_decorator
def square(n):
return n*n
square(4) # Output: 16
square('a') # TypeError: Unexpected type: <class 'str'>, expected int, float, or complex
从上面的代码中可以看到,装饰器verify_number_decorator 运行在square() 函数上。如果函数的参数 n 不是数字类型的,会抛出一个TypeError 异常。如果 n 是数字类型,则会返回 n 的平方。
3. 授权访问
另一个常见的用例是授权访问。例如,我们可以创建一个装饰器来检查当前用户是否具有某个资源的访问权限:
def check_permission_decorator(func):
def wrapper(*args, **kwargs):
if not validate_user_permission():
raise PermissionError("You are not authorized to access this resource")
return func(*args, **kwargs)
return wrapper
@check_permission_decorator
def view_confidential_document():
print("This is a confidential document")
view_confidential_document()
在这个示例中,check_permission_decorator装饰器检查当前用户是否有足够的权限来查看机密文档。如果用户没有权 限,则会引发一个权限错误。否则,函数将继续执行,打印机密文档。
4. 缓存函数结果
最后一个示例是使用装饰器来缓存函数的计算结果。缓存是一种常见的技术,可以加速某些函数的执行。我们可以使用一个装饰器来自动缓存函数的结果。如果相同的参数再次传递给函数,那么函数直接返回缓存的结果,而不需要再次计算。
def memoize_decorator(func):
cache = {}
def wrapper(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@memoize_decorator
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(50))
在这个示例中,memoize_decorator装饰器在使用递归计算斐波那契序列时进行缓存。此设施将计算结果存储在 cache 字典中,如果再次传递相同的参数,则函数直接返回缓存的结果,而不需要再次计算。这将大大加速斐波那契序列的计算。
编写自己的装饰器
现在我们已经看到了一些实际的例子,让我们看看如何编写自己的装饰器。
编写装饰器的步骤如下:
1. 创建一个包裹函数。这个函数将接受一个函数作为参数并返回一个新函数。
2. 在这个包裹函数中,编写任何你想要增强的代码、修改等——尤其是继承实际的函数。
3. 返回新内嵌的函数。
这里是一个简单的装饰器示例:
def my_decorator(func):
def wrapper(*args, **kwargs):
# Wrapped code goes here
print("Something is happening before the function is called.")
func(*args, **kwargs)
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello(name):
print(f'Hello {name}')
say_hello('John')
这个装饰器不需要任何参数。它的作用是输出一些信息来增强say_hello()函数的功能。
需要注意的是,装饰器通常不会修改原函数的参数和返回值。它们只是简单地扩展或包装原函数。
总结
Python装饰器是一种非常有用的编程工具,可以用于动态地修改或增强函数的功能。这篇文章介绍了一些常见的用例,包括记录函数执行时间、检查函数参数、授权访问和缓存函数结果。我们还学习了如何编写自己的装饰器。装饰器是 Python 语言中的一个重要特性,掌握这个特性将使您成为一个更加熟练的程序员。
