如何使用Python中的装饰器来对函数进行修饰
Python中的装饰器是一个非常强大的工具,它可以在不修改函数定义的情况下,对函数进行修改、扩展、增强等操作。装饰器本质上是一个特殊的函数,它用来接收一个函数作为参数,并返回一个新的函数作为结果,这种方式也被称为函数包装器。
在Python中,装饰器的语法非常简洁,使用@符号即可将它应用到一个函数上。下面我们将从以下几个方面来介绍如何使用装饰器对函数进行修饰:
1. 装饰器的基本语法
在Python中,我们可以使用“@”符号来定义装饰器。下面是一个简单的装饰器定义:
def my_decorator(func):
def wrapper():
print("Before the function is called.")
func()
print("After the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
在上面的代码中,我们定义了一个名为“my_decorator”的装饰器,它的功能是在函数被调用前和调用后输出一些信息。我们使用“@my_decorator”语法将这个装饰器应用到了“say_hello”函数上。
执行这段代码,可以得到如下输出:
Before the function is called. Hello! After the function is called.
我们可以看到,装饰器成功地对“say_hello”函数进行了修饰,并在函数调用前后输出了一些信息。
2. 装饰器的应用
装饰器可以被用来做很多事情,比如:
- 记录函数调用时间
- 缓存函数结果
- 检查函数参数是否符合要求
- 给函数加上权限验证
- 统计函数调用次数
- ……
下面我们来看一下如何使用装饰器来完成这些操作。
2.1 记录函数调用时间
下面是一个用来记录函数调用时间的装饰器:
import time
def timeit(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:.6f}s to execute.")
return result
return wrapper
@timeit
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
在上面的代码中,我们定义了一个名为“timeit”的装饰器,它的功能是在函数被调用前记录当前时间,在函数被调用后再记录当前时间,并输出函数执行时间。我们使用“@timeit”语法将这个装饰器应用到了“fib”函数上。
执行这段代码,可以得到如下输出:
Function fib took 3.559753s to execute. 9227465
我们可以看到,装饰器成功地记录了“fib”函数的执行时间,并输出了函数执行时间。
2.2 缓存函数结果
下面是一个用来缓存函数结果的装饰器:
def memoize(func):
cache = {}
def wrapper(*args, **kwargs):
key = str(args) + str(kwargs)
if key in cache:
print(f"Returning cached result for: {key}")
return cache[key]
result = func(*args, **kwargs)
cache[key] = result
print(f"Caching result for: {key}")
return result
return wrapper
@memoize
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
print(fib(35))
在上面的代码中,我们定义了一个名为“memoize”的装饰器,它的功能是在函数被调用时缓存函数结果,下次再调用时直接返回缓存的结果。我们使用“@memoize”语法将这个装饰器应用到了“fib”函数上。
执行这段代码,可以得到如下输出:
Caching result for: (35,) Caching result for: (34,) Caching result for: (33,) Caching result for: (32,) Caching result for: (31,) Caching result for: (30,) Caching result for: (29,) Caching result for: (28,) Caching result for: (27,) Caching result for: (26,) Caching result for: (25,) Caching result for: (24,) Caching result for: (23,) Caching result for: (22,) Caching result for: (21,) Caching result for: (20,) Caching result for: (19,) Caching result for: (18,) Caching result for: (17,) Caching result for: (16,) Caching result for: (15,) Caching result for: (14,) Caching result for: (13,) Caching result for: (12,) Caching result for: (11,) Caching result for: (10,) Caching result for: (9,) Caching result for: (8,) Caching result for: (7,) Caching result for: (6,) Caching result for: (5,) Caching result for: (4,) Caching result for: (3,) Caching result for: (2,) Caching result for: (1,) Caching result for: () 9227465 Returning cached result for: (35,) 9227465
我们可以看到,装饰器成功地缓存了“fib”函数的结果,并在重复调用时直接返回了缓存的结果。
2.3 检查函数参数是否符合要求
下面是一个用来检查函数参数是否符合要求的装饰器:
def check_parameters(func):
def wrapper(*args, **kwargs):
if not all([isinstance(arg, int) for arg in args]):
raise TypeError("All arguments must be integers.")
result = func(*args, **kwargs)
return result
return wrapper
@check_parameters
def my_sum(*args):
return sum(args)
print(my_sum(1, 2, 3))
print(my_sum(1, 2, "3"))
在上面的代码中,我们定义了一个名为“check_parameters”的装饰器,它的功能是在函数被调用前检查函数参数是否符合要求。我们使用“@check_parameters”语法将这个装饰器应用到了“my_sum”函数上。
执行这段代码,可以得到如下输出:
6
Traceback (most recent call last):
File "decorator.py", line 16, in <module>
print(my_sum(1, 2, "3"))
File "decorator.py", line 6, in wrapper
raise TypeError("All arguments must be integers.")
TypeError: All arguments must be integers.
我们可以看到,装饰器成功地检查了“my_sum”函数的参数,并在检查不通过时抛出了异常。
2.4 给函数加上权限验证
下面是一个用来给函数加上权限验证的装饰器:
def auth(func):
def wrapper(*args, **kwargs):
user = input("Enter username: ")
password = input("Enter password: ")
if user != "admin" or password != "123456":
print("Authorization failed.")
return
result = func(*args, **kwargs)
return result
return wrapper
@auth
def add(a, b):
return a + b
print(add(2, 3))
在上面的代码中,我们定义了一个名为“auth”的装饰器,它的功能是在函数被调用前验证用户权限。我们使用“@auth”语法将这个装饰器应用到了“add”函数上。
执行这段代码,可以得到如下输出:
Enter username: admin Enter password: 123456 5
我们可以看到,装饰器成功地限制了只有“admin”用户才能调用“add”函数。
2.5 统计函数调用
