Python 装饰器:函数的函数,代码的艺术

引言

在Python中,装饰器是一种强大的功能,允许程序员在不修改原函数源码的情况下增强或修改函数行为。装饰器本质上是一个接收函数作为参数的高阶函数,并返回一个新的函数或修改原函数的行为。这种机制极大地提高了代码的复用性、可读性和模块化程度。

装饰器基础

装饰器的基本语法如下:

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # 执行一些前置操作
        print("Before calling the original function.")
        
        # 调用原函数
        result = original_function(*args, **kwargs)
        
        # 执行一些后置操作
        print("After calling the original function.")
        
        # 返回原函数的结果
        return result
    return wrapper
使用装饰器

要在函数上应用装饰器,只需在函数定义前加上 @decorator_name 即可:

@decorator_function
def target_function(arg1, arg2):
    print(f"Inside target function with args: {arg1}, {arg2}")

这相当于:

def target_function(arg1, arg2):
    print(f"Inside target_function with args: {arg1}, {arg2}")

target_function = decorator_function(target_function)
带参数的装饰器

装饰器不仅可以作用于函数,还可以带有参数,这使得装饰器本身具有更多的灵活性。下面是一个带参数的装饰器示例,它使函数重复执行指定次数:

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

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

greet("Alice")  # 输出 Hello, Alice! 三次
类装饰器

类装饰器是一个包含 __call__ 方法的类。当装饰器被应用时,__call__ 方法被调用,它接收原函数作为参数,并返回新的函数。

class DecoratorClass:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Before calling the original function.")
        result = self.func(*args, **kwargs)
        print("After calling the original function.")
        return result

@DecoratorClass
def my_function():
    print("Inside my_function.")

my_function()  # 输出 Before, Inside, After
装饰器应用场景

装饰器在Python中有着广泛的应用,包括但不限于:

  • 日志记录:记录函数的调用信息、参数和返回值。
  • 性能分析:测量函数的执行时间。
  • 权限控制:限制对某些函数的访问权限。
  • 缓存:存储函数结果以提高性能。
  • 事务管理:在数据库操作前后进行资源锁定和释放。
总结

装饰器是Python语言的特色之一,它允许我们以一种简洁、优雅的方式扩展函数或类的功能。通过理解和运用装饰器,我们可以写出更加灵活、模块化的代码,提高开发效率,同时保持代码的清晰和可维护性。无论是对于初学者还是经验丰富的开发者,掌握装饰器的使用都将是一笔宝贵的财富。

posted @   燕鹏  阅读(11)  评论(0编辑  收藏  举报  
(评论功能已被禁用)
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示