Python中关于装饰器的使用问题,萌新求助

stackoverflow 中 How to make a chain of function decorators?( https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators )中,最高票答案(目前为 3560 票)的“ Let ’ s practice: decorating a decorator ”部分第一个装饰器的具体作用是什么?请详细讲一下。

该装饰器如下:

——————————————————————

def decorator_with_args(decorator_to_enhance):

# We use the same trick we did to pass arguments
def decorator_maker(*args, **kwargs):
# We create on the fly a decorator that accepts only a function
# but keeps the passed arguments from the maker.
def decorator_wrapper(func):

    # We return the result of the original decorator, which, after all, 
    # IS JUST AN ORDINARY FUNCTION (which returns a function).
    # Only pitfall: the decorator must have this specific signature or it won't work:
    return decorator_to_enhance(func, *args, **kwargs)

return decorator_wrapper

return decorator_maker


Python中关于装饰器的使用问题,萌新求助

5 回复

有没有大佬帮忙看一下


装饰器这玩意儿说白了就是个语法糖,让你在不改原函数代码的情况下给它加功能。最常用的场景就是日志记录、性能测试、权限校验这些。

给你看个最基础的例子:

def my_decorator(func):
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

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

say_hello()

运行这个,你会看到:

函数执行前
Hello!
函数执行后

这里@my_decorator就相当于say_hello = my_decorator(say_hello)。装饰器函数my_decorator接收一个函数作为参数,然后返回一个新的函数wrapper,这个新函数在调用原函数前后加了点操作。

如果要装饰带参数的函数,得这么写:

def decorator_with_args(func):
    def wrapper(*args, **kwargs):
        print(f"调用 {func.__name__},参数: {args}, {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@decorator_with_args
def add(a, b):
    return a + b

print(add(3, 5))

*args**kwargs就能处理任意参数了。

还有个高级点的玩法,装饰器自己也能带参数:

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

@repeat(num_times=3)
def greet(name):
    print(f"Hello {name}")

greet("World")

这个会让greet函数执行3次。

实际项目中,@functools.wraps(func)这个装饰器一定要用,它能保留原函数的元信息(比如函数名、文档字符串这些):

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print("装饰器逻辑")
        return func(*args, **kwargs)
    return wrapper

类也能当装饰器用,实现__call__方法就行。多个装饰器的话,执行顺序是从下往上(离函数定义最近的先执行)。

总结:装饰器就是个包装函数的高阶函数,理解闭包是关键。

装饰器是单纯的套娃语法糖

具体看套的是什么


有的是闭包 有的是描述器


上面那个是闭包

套一层只能传不带参数的函数
套二层能传函数参数
套三层能传入预参数

顺便说下 。上面那种写法用得少一点 属于先套函数参数再套函数的


一般写法是先套 fun

谢谢大佬,昨晚在一哥们指导下已经看明白了,今天一看大佬回复,更加深了理解。么么哒

回到顶部