如果您希望裝飾器接受參數,那麼使用基於類的裝飾器是一種方法。根據我的經驗,他們最終能夠更輕鬆地進行推理和維護。它們很簡單,__init__
接受裝飾器的任何參數,__call__
返回裝飾函數。其中一個寫裝飾器的問題是如果它們傳遞參數或者不參與,它們的行爲完全不同。這是很容易在基於類的裝飾,以解決這個問題,讓你的裝飾,以接受參數或不:
class target:
def __init__(self, targets):
"""Arguments for decorator"""
self.targets = None
if not hasattr(targets, '__call__'):
# check we are actually passed arguments!
# if targets has __call__ attr, we were called w/o arguments
self.targets = targets
def __call__(self, f):
"""Returns decorated function"""
if self.targets:
def newf(*args, **kwargs):
for target in self.targets:
f(target)
return newf
else:
return f
現在,如果我們使用參數的裝飾,它會按預期工作,調用我們的函數3倍:
>>> @target([1,2,3])
..: def foo(x): print x
...
>>> foo()
1
2
3
但是,如果我們不帶參數調用,我們將返回,而不是原來的功能:
>>> @target
def foo(x): print x
..:
>>> foo(3)
<<< 3
偉大的答案,但我發現基於類的裝飾更容易使用我的工作n裝飾者接受參數/戰士的情況。 – zeekay 2011-05-09 18:58:59
感謝您的想法。 – ycseattle 2011-05-09 21:34:45
我和OP有相同的需求。但是你的建議並不適合我。我遇到的第一個問題是解決方案相當簡單。裝飾器需要應用於一個方法,但你的答案中的「裝飾器」不需要「自我」參數。另一個問題似乎更成問題。測試運行者將在循環之外調用適當的設置和清理方法。這意味着狀態不會在測試用例之間得到清理,就像使用兩個單獨的'test_'函數一樣。這會導致測試用例失敗。 – kasperd 2014-12-16 14:05:34