Python装饰器的应用及实现
Python装饰器是一种高级编程特性,它可以被用来修改或扩展函数的功能。使用Python装饰器,可以在不改变原有代码的情况下,对函数进行增强。
Python装饰器常见的应用场景包括:
1. 记录日志:在代码执行某些操作时,记录相关的日志信息。
2. 缓存结果:对于一个重复执行的函数,可以使用装饰器对其结果进行缓存,使得代码运行更快。
3. 用户权限:在用户登录后,可以检查其是否具有执行某些操作的权限。
4. 输入/输出格式化:对于输入或输出数据的处理,可以使用装饰器对其进行格式化。
接下来我们将分别介绍如何实现这些装饰器。
一、记录日志装饰器
记录日志是一种重要的应用场景,在代码执行时,可以使用装饰器对其进行记录。实现一个记录日志的装饰器,可以使用Python的装饰器语法,将一个函数嵌套在另一个函数中,如下所示:
def log(func):
def wrapper(*args, **kwargs):
print('Calling function:', func.__name__)
print('Arguments:', args, kwargs)
return func(*args, **kwargs)
return wrapper
在上面的代码中,我们定义了一个log函数,用来实现记录日志的功能。它接收一个函数作为参数,然后返回一个嵌套函数wrapper。当调用函数时,wrapper函数先打印出一些信息,再调用原函数,并返回函数的执行结果。
下面是一个实例,用来展示如何使用该装饰器:
@log
def add(x, y):
return x+y
result = add(3, 4)
print(result)
运行上述代码,将会得到以下输出:
Calling function: add
Arguments: (3, 4) {}
7
我们可以看到,每次调用add函数时,都会输出一行日志信息。
二、缓存结果装饰器
缓存结果也是一个常见的应用场景,我们可以使用装饰器来避免重复计算,并加速程序运行速度。下面是实现一个缓存结果的装饰器:
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
在上述代码中,我们定义了一个cache函数,用于实现缓存结果的功能。它接受一个函数作为参数func,再定义一个字典cached_results,用于保存函数计算结果。wrapper函数检查是否已经计算过,如果已经缓存,则返回结果,否则调用原函数,计算并缓存结果。
下面是一个示例,用来展示如何使用该装饰器:
@cache
def add(x, y):
return x+y
result1 = add(3, 4)
result2 = add(3, 4)
print(result1, result2)
运行上述代码,我们可以看到,函数add只会在 次调用时进行计算,后续的调用将直接返回缓存结果:
7 7
三、用户权限装饰器
用户权限也是一个常见的应用场景,我们可以在函数内部检查用户是否有权限执行某个操作。下面是实现一个用户权限装饰器:
def check_permission(required_permission):
def wrapper(func):
def inner_wrapper(*args, **kwargs):
user = kwargs.get('user')
if user and user.has_permission(required_permission):
return func(*args, **kwargs)
raise Exception('Permission Denied')
return inner_wrapper
return wrapper
在上述代码中,我们定义了一个check_permission函数,用于实现用户权限的功能。它接收一个参数required_permission,表示所需权限。然后定义一个嵌套函数wrapper,用于包装原函数。inner_wrapper函数接收所有的参数,并检查用户是否具有所需权限,如果有,则执行原函数,否则抛出异常。
下面是一个示例,用来展示如何使用该装饰器:
class User:
def __init__(self, permissions):
self.permissions = permissions
def has_permission(self, permission):
return permission in self.permissions
def __str__(self):
return 'User ' + str(self.permissions)
@check_permission('can_write')
def write_file(*args, **kwargs):
print('Writing file...')
user1 = User(['can_read', 'can_write'])
try:
write_file(user=user1)
except Exception as ex:
print(ex)
user2 = User(['can_read'])
try:
write_file(user=user2)
except Exception as ex:
print(ex)
运行上述代码,我们可以看到,当具有写权限的用户调用函数时会执行,否则抛出异常:
Writing file... Permission Denied
四、输入/输出格式化装饰器
输入/输出格式化也是一个常见的应用场景,我们可以使用装饰器对输入/输出数据进行格式化。下面是一个实现输入/输出格式化的装饰器:
def format_input(func):
def wrapper(*args, **kwargs):
formatted_args = [float(arg) for arg in args]
formatted_kwargs = {key: float(value) for key, value in kwargs.items()}
return func(*formatted_args, **formatted_kwargs)
return wrapper
def format_output(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return '{:.2f}'.format(float(result))
return wrapper
在上述代码中,我们定义了两个装饰器,分别用于格式化输入和输出。format_input函数用于将输入的所有参数,包括关键字参数都转换为浮点数。format_output函数用于将函数返回值转换为两位小数的字符串。
下面是一个示例,用来展示如何使用这两个装饰器:
@format_input
@format_output
def multiply(x, y):
return x*y
result = multiply('3', y=4)
print(result)
运行上述代码,我们可以看到,函数执行结束后,得到的结果被转换成了字符串'12.00':
12.00
总结:
Python装饰器是非常强大的工具,可以将许多功能,如记录日志、缓存结果、权限验证、输入/输出格式化等扩展到函数上。除了上述场景外,Python装饰器还有许多其他的用途。熟练掌握装饰器的使用,对于开发高效、易于维护的Python代码非常有帮助。
