def custom_decorator(func):
call_count = 0
def wrapper(*args, **kwargs):
nonlocal call_count
call_count += 1
print(f"函数 {func.__name__} 调用次数: {call_count}")
print(f"传入的位置参数: {args}")
print(f"传入的关键字参数: {kwargs}")
result = func(*args, **kwargs)
if '特定关键字参数' in kwargs and kwargs['特定关键字参数']:
if isinstance(result, str):
result = result.upper()
return result
return wrapper
@custom_decorator
def test_function(a, b, c=False):
return f"{a} {b}"
元编程概念
- 装饰器本身就是元编程的体现:元编程是指程序可以在运行时操纵自身或其他程序的结构和行为。装饰器允许我们在不修改函数源代码的情况下,为函数添加额外的功能。这里的装饰器
custom_decorator
就是在运行时动态地给 test_function
添加了记录调用次数和参数,以及根据参数修改行为的功能。
- 闭包:在装饰器实现中,
wrapper
函数形成了闭包。闭包是指内部函数可以访问外部函数的变量,即使外部函数已经返回。这里 wrapper
函数可以访问并修改 call_count
变量,即使 custom_decorator
函数已经执行完毕返回 wrapper
函数对象。
确保通用性和可扩展性
- 通用性:
- 接受任意参数:装饰器内部的
wrapper
函数使用 *args
和 **kwargs
来接受任意数量和类型的位置参数和关键字参数。这样,无论被装饰的函数定义了怎样的参数列表,装饰器都可以正常工作。
- 不依赖函数返回值类型:在对返回值进行处理时,通过
isinstance
判断返回值类型,而不是假设其类型。例如,只对字符串类型的返回值进行转大写操作,这样可以适应不同返回值类型的函数。
- 可扩展性:
- 易于添加新功能:如果需要添加新的功能,比如记录函数执行时间,只需要在
wrapper
函数内部适当位置添加代码即可,不会影响到被装饰函数和其他功能。
- 参数化行为:通过关键字参数来动态修改函数行为,使得装饰器具有灵活性。例如,通过
特定关键字参数
来决定是否对返回值进行转换。如果需要更多的动态行为,可以添加更多的关键字参数,并在 wrapper
函数中相应处理。