Python 有参装饰器

Python 有参装饰器

装饰器的基本概念

装饰器本质上是一个函数,它接收另一个函数作为参数,并返回一个新的函数,从而在函数执行前后添加一些额外的功能。

以下是一个简单的无参装饰器示例:

python 复制代码
def simple_decorator(func):
    def wrapper():
        print("Function is about to be called.")
        func()
        print("Function has been called.")
    return wrapper

@simple_decorator
def my_function():
    print("Hello, World!")

my_function()

输出:

python 复制代码
Function is about to be called.
Hello, World!
Function has been called.

有参装饰器是什么?

有参装饰器是装饰器的扩展版本,它不仅可以接收一个函数作为参数,还可以接收其他自定义参数。通过这些自定义参数,我们可以控制装饰器的行为,使其变得更加灵活。

有参装饰器的结构

有参装饰器的实现有点复杂,因为它实际上是一个三层函数嵌套:

  1. 最外层函数:用于接收参数,返回真正的装饰器。
  2. 中间层函数(即装饰器本身):接收要装饰的函数作为参数。
  3. 最内层函数:包装原函数,并在其中添加额外的功能。

有参装饰器的实现

假设我们要创建一个装饰器,它接收一个布尔值参数,控制是否启用装饰器中的额外功能。

python 复制代码
def debug(enabled):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if enabled:
                print(f"Calling function {func.__name__} with arguments {args} and {kwargs}")
            result = func(*args, **kwargs)
            if enabled:
                print(f"Function {func.__name__} returned {result}")
            return result
        return wrapper
    return decorator

@debug(enabled=True)
def add(a, b):
    return a + b

@debug(enabled=False)
def multiply(a, b):
    return a * b

# 调用函数
print(add(3, 4))        # 输出调试信息
print(multiply(3, 4))   # 不输出调试信息

输出:

python 复制代码
Calling function add with arguments (3, 4) and {}
Function add returned 7
7
12

在这个例子中,装饰器 debug 接收一个 enabled 参数,用于控制是否启用调试功能:

  1. 如果 enabled 为 True,则装饰器会在函数调用前后打印调试信息。
  2. 如果 enabled 为 False,则装饰器不会打印任何额外信息,只执行原函数。

结构拆解

  1. 最外层函数 debug(enabled):这个函数接收一个参数 enabled,并返回真正的装饰器 decorator。
  2. 中间层函数 decorator(func):这个函数接收要装饰的原函数 func,并返回包装后的函数 wrapper。
  3. 最内层函数 wrapper(*args, **kwargs):这是实际执行装饰和功能增强的地方,接收原函数的参数并添加额外的逻辑。

有参装饰器的常见用例

1. 控制调试输出

在前面的例子中,我们通过参数控制是否启用调试功能。这在需要动态启用或禁用调试信息的场景中非常有用。

2. 设置函数执行的最大次数

我们可以通过参数来控制某个函数的最大执行次数。例如,创建一个装饰器,用于限制函数最多只能被调用指定的次数。

python 复制代码
def limit_calls(max_calls):
    def decorator(func):
        func.calls = 0
        
        def wrapper(*args, **kwargs):
            if func.calls >= max_calls:
                print(f"Function {func.__name__} has reached its limit of {max_calls} calls.")
                return
            func.calls += 1
            return func(*args, **kwargs)
        
        return wrapper
    return decorator

@limit_calls(3)
def greet(name):
    print(f"Hello, {name}!")

# 测试调用
greet("Alice")
greet("Bob")
greet("Charlie")
greet("Dave")  # 第四次调用,超过限制

在这个例子中,装饰器 limit_calls 限制了函数 greet 的调用次数。超过指定次数后,函数不会再执行。

3. 验证用户权限

在某些场景中,我们可能需要根据不同用户的权限来控制函数的执行。通过有参装饰器,我们可以根据传入的权限参数来检查用户是否有权限执行特定的函数。

python 复制代码
def require_permission(permission):
    def decorator(func):
        def wrapper(user, *args, **kwargs):
            if user.get('permission') == permission:
                return func(user, *args, **kwargs)
            else:
                print(f"User does not have {permission} permission.")
        return wrapper
    return decorator

@require_permission('admin')
def delete_user(user, user_id):
    print(f"User {user_id} deleted by {user['name']}")

# 测试用户权限
admin_user = {'name': 'Alice', 'permission': 'admin'}
regular_user = {'name': 'Bob', 'permission': 'user'}

delete_user(admin_user, 1)  # 执行成功
delete_user(regular_user, 2)  # 无权限执行

总结

有参装饰器 是装饰器的强大扩展,它允许我们在装饰函数时动态传递参数,从而更灵活地控制装饰器的行为。在日常开发中,有参装饰器广泛应用于调试控制、访问控制、调用次数限制等场景。

有参装饰器的核心是三层函数嵌套结构:

  1. 最外层函数 用于接收参数。
  2. 中间层函数 是实际的装饰器,接收要装饰的函数。
  3. 最内层函数 负责增强功能,包装原函数并执行额外的逻辑

相关推荐
枫叶丹46 分钟前
【Qt开发】常用控件(四)
开发语言·qt
草莓熊Lotso14 分钟前
《吃透 C++ 类和对象(中):const 成员函数与取地址运算符重载解析》
c语言·开发语言·c++·笔记·其他
跟橙姐学代码21 分钟前
学Python像学做人:从基础语法到人生哲理的成长之路
前端·python
weixin_3077791323 分钟前
VS Code配置MinGW64编译Ipopt库
开发语言·c++·vscode·算法
Tadas-Gao27 分钟前
Java设计模式全景解析:从演进历程到创新实践
java·开发语言·微服务·设计模式·云原生·架构·系统架构
Keying,,,,33 分钟前
力扣hot100 | 矩阵 | 73. 矩阵置零、54. 螺旋矩阵、48. 旋转图像、240. 搜索二维矩阵 II
python·算法·leetcode·矩阵
桃源学社(接毕设)1 小时前
基于人工智能和物联网融合跌倒监控系统(LW+源码+讲解+部署)
人工智能·python·单片机·yolov8
yunhuibin1 小时前
pycharm2025导入anaconda创建的各个AI环境
人工智能·python
杨荧1 小时前
基于Python的电影评论数据分析系统 Python+Django+Vue.js
大数据·前端·vue.js·python
anlogic1 小时前
Java基础 8.16
java·开发语言