問題描述
自己寫了個帶參數的裝飾器,現在需要裝飾器隨著不同條件使用不同的參數。
問題出現的環境背景及自己嘗試過哪些方法
自己寫了個帶參數的裝飾器,現在需要裝飾器隨著不同條件使用不同的參數。如下,利用一個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()
請大神解釋到底是為什么???謝謝!
1 回答

holdtom
TA貢獻1805條經驗 獲得超10個贊
“帶參數的裝飾器”,這樣的描述并不準確,@desc(arg)
更好的理解是函數 desc
被調用,該函數返回一個裝飾器。況且你已經知道處理方法了,只是想要知道為什么。這點上是一點就通的。
先理解一個,函數允許重新賦值的
def f():
pass
f = 1
print(f) # 1
然后你對裝飾器的理解也已經很充分了:
@log(i, j, k)
def f():
# 等價于
tmp = log(i,j,k)
@tmp
def f():
這里的原因在于,你把 log
重新賦值了,它變成了一個裝飾器,而不是一個返回裝飾器的函數。嗯,原因就是這么簡單。
添加回答
舉報
0/150
提交
取消