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中关于装饰器的使用问题,萌新求助
有没有大佬帮忙看一下
装饰器这玩意儿说白了就是个语法糖,让你在不改原函数代码的情况下给它加功能。最常用的场景就是日志记录、性能测试、权限校验这些。
给你看个最基础的例子:
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


