问题描述
自己写了个带参数的装饰器,现在需要装饰器随着不同条件使用不同的参数。
问题出现的环境背景及自己尝试过哪些方法
自己写了个带参数的装饰器,现在需要装饰器随着不同条件使用不同的参数。
如下,利用一个for循环将不通的参数传进装饰器(这种时候是可以使用的):
from functools import wraps
def log(a, b, c):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('hello', str(a), str(b), str(c), func.__name__)
func(*args, **kwargs)
print('goodbye', str(a), str(b), str(c), func.__name__)
return wrapper
return decorator
a_l, b_l, c_l = [1, 2, 3], [4, 5, 6], [7, 8, 9]
l = list(range(5))
for i, j, k in zip(a_l, b_l, c_l):
@log(i, j, k)
def f():
print('ok')
f()
但是现在假设我的装饰器有很多参数,而且for循环内部也有很多函数,我不想每一个装饰器都写那么多参数,于是想先给装饰器传好参数,但是确报错了如下:
from functools import wraps
def log(a, b, c):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('hello', str(a), str(b), str(c), func.__name__)
func(*args, **kwargs)
print('goodbye', str(a), str(b), str(c), func.__name__)
return wrapper
return decorator
a_l, b_l, c_l = [1, 2, 3], [4, 5, 6], [7, 8, 9]
l = list(range(5))
for i, j, k in zip(a_l, b_l, c_l):
log = log(i, j, k)
@log
def f():
print('ok')
f()
#报错
hello 1 4 7 f
ok
goodbye 1 4 7 f
Traceback (most recent call last):
File "D:\test\ttt.py", line 22, in <module>
log = log(i, j, k)
TypeError: decorator() takes 1 positional argument but 3 were given
可以看到很怪的是第一个循环的时候是可以用的有输出,但是到了第二个for循环的时候装饰器传参却出现了错误,不知道是为什么?请问到底错在了那里?谢谢!
更奇怪的是,我换了个函数别名竟然就可以用了。。。,代码如下:
from functools import wraps
def log(a, b, c):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('hello', str(a), str(b), str(c), func.__name__)
func(*args, **kwargs)
print('goodbye', str(a), str(b), str(c), func.__name__)
return wrapper
return decorator
a_l, b_l, c_l = [1, 2, 3], [4, 5, 6], [7, 8, 9]
l = list(range(5))
for i, j, k in zip(a_l, b_l, c_l):
lg = log(i, j, k) # 把原来的log,换成了lg就可以正常运行了
@lg
def f():
print('ok')
f()
请大神解释到底是为什么???谢谢!
“带参数的装饰器”,这样的描述并不准确,
@desc(arg)
更好的理解是函数desc
被调用,该函数返回一个装饰器。况且你已经知道处理方法了,只是想要知道为什么。这点上是一点就通的。先理解一个,函数允许重新赋值的
然后你对装饰器的理解也已经很充分了:
这里的原因在于,你把
log
重新赋值了,它变成了一个装饰器,而不是一个返回装饰器的函数。嗯,原因就是这么简单。