加载中...

python装饰器

定义

在python中, 装饰器是一种非常强大且常用的语法结构, 它允许你在不修改原函数代码的前提下, 增强或修改函数的行为。装饰器本质上是一个接受函数作为参数的函数, 并返回一个新的函数。

装饰器的基本概念

最简单的装饰器示例:

def my_decorator(func):
    def wrapper():
        print('装饰器: 函数执行前')
        func()
        print('装饰器: 函数执行后')
    return warpper


@my_decorator
def say_hello():
    print("Hello!")

say_hello()

输出结果:

装饰器:函数执行前
Hello!
装饰器:函数执行后

装饰器的工作原理

上面的列子等价于

def say_hello():
    print('Hello!')
    
say_hello = my_decorator(say_hello)
say_hello()

也就是说,装饰器 @my_decorator 就是把被装饰的函数传给装饰器函数,并用返回的新函数替换原来的函数。

带参数的函数装饰器

如果被装饰的函数有参数,需要给wrapper 加上参数

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print('装饰器: 函数执行前')
        func(*args, **kwargs)
        print('装饰器: 函数执行后')
    return warpper

@my_decorator
def greet_name(name):
    print(f'hello {name}!')
    
greet_name('小明')
    

带参数的装饰器(装饰器工厂)

如果你想让装饰器本身也能接受参数,需要再嵌套一层函数

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

@repeat(3)
def say_hi():
    print("Hi!")

say_hi()

输出:

深色版本

Hi!
Hi!
Hi!

多个装饰器叠加使用

你可以为一个函数添加多个装饰器,它们会按照从上到下的顺序依次包装函数

def decorator1(func):
    def wrapper():
        print("装饰器1进入")
        func()
        print("装饰器1退出")
    return wrapper

def decorator2(func):
    def wrapper():
        print("装饰器2进入")
        func()
        print("装饰器2退出")
    return wrapper

@decorator1
@decorator2
def do_something():
    print("执行任务")

do_something()

执行顺序分析:

相当于:do_something = decorator1(decorator2(do_something))

输出:

深色版本

装饰器1进入
装饰器2进入
执行任务
装饰器2退出
装饰器1退出

保留元数据:使用functools.wraps

当你使用装饰器时,默认情况下,被装饰函数的元信息(如 __name__, __doc__)会被 wrapper 替换。为了保留这些信息,可以使用 functools.wraps

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        '''这是装饰器中的函数'''
        print("装饰器前操作")
        result = func(*args, **kwargs)
        print("装饰器后操作")
        return result
    return wrapper

@my_decorator
def example():
    """这是一个示例函数"""
    print("示例函数执行中")

print(example.__name__)   # 输出: example(而不是 wrapper)
print(example.__doc__)    # 输出: 这是一个示例函数(而不是这是装饰器中的函数)
posted @ 2025-06-15 17:32  最大的敌人是自律  阅读(16)  评论(0)    收藏  举报