至於其他的答案已經解釋,裝飾通常當只使用他們的名字像這樣調用通過一個單一的隱函數的參數:
@deco
def somefunc(...): pass
哪個做同樣的事情:
def somefunc(...): pass
somefunc = deco(somefunc)
在這種情況下的參數是緊接着的函數定義的編譯版本。在這種情況下,裝飾器返回一個可分配給函數名稱而不是編譯函數體的可調用對象,正如通常情況那樣。
但是,如果一個裝飾功能明確給出一個或多個參數時,它被調用,就像這樣:
@deco(args)
def somefunc(...): pass
它變成相當於:
def somefunc(...): pass
somefunc = deco(args)(somefunc)
正如你可以看到,在這個事情案件的工作有些不同。裝飾器函數仍然返回一個可調用的函數,這次只有需要一個「普通」的單一隱式參數裝飾器函數,然後像以前一樣用以下函數定義中的函數對象調用它。
再次–正如其他人指出–這使得裝飾明確地傳遞參數,裝飾工廠在這個意義上,他們建立並返回「常規」裝飾功能。
在大多數情況下(如果不是全部),裝飾器可以作爲函數或類來實現,因爲兩者都可以在Python中調用。就我個人而言,我發現函數更容易理解,因此將在下面使用該方法。另一方面,函數方法可能會變得棘手,因爲它通常涉及一個或多個嵌套函數定義。
下面介紹如何在模塊中爲do()
函數編寫裝飾器。在下面的代碼中,我定義了它在調用它之前打印出函數的參數。
def do(fn, args=tuple(), kwargs={}, priority=0,
block=False, timeout=0, callback=None, daemon=False):
# show arguments
print ('in do(): fn={!r}, args={}, kwargs={}, priority={},\n'
' block={}, timeout={}, callback={}, daemon={}'
.format(fn.__name__, args, kwargs, priority,
block, timeout, callback, daemon))
# and call function 'fn' with its arguments
print (' calling {}({}, {})'.format(
fn.__name__,
', '.join(map(str, args)) if args else '',
', '.join('{}={}'.format(k, v) for k,v in kwargs.items())
if kwargs else '')
)
fn(*args, **kwargs)
def do_decorator(**do_kwargs):
def decorator(fn):
def decorated(*args, **kwargs):
do(fn, args, kwargs, **do_kwargs)
return decorated
return decorator
@do_decorator(priority=2)
def decoratedTask(arg, dic=42):
print 'in decoratedTask(): arg={}, dic={}'.format(arg, dic)
decoratedTask(72, dic=3)
輸出:
in do(): fn='decoratedTask', args=(72,), kwargs={'dic': 42}, priority=2,
block=False, timeout=0, callback=None, daemon=False
calling decoratedTask(72, dic=3)
in decoratedTask(): arg=72, dic=3
這裏的竄缸打擊帳戶的這個複雜的尋找的東西是如何工作的:
外裝飾功能do_decorator()
,定義它返回另一個內部裝飾功能,這裏創造性地命名爲decorator
。
做什麼decorator
是確定會發生什麼了在一個簡單的裝飾「不爭論」的情況—,此處可確定和返回另一個–但最終–嵌套函數調用decorated
,這只是調用該模塊的do()
功能和功能如果從調用的角度來看,則將它傳遞給參數,以及用於do()
函數的參數。
這個用例有點複雜,因爲外部裝飾器和正在裝飾的函數都有關鍵字參數。需要特別注意確保每個關鍵字的名稱都是唯一的,這樣它們就不會發生衝突(並且可變kwargs
參數默認值不會因do()
函數中的某些內容而無意中更改)。
感謝這使得它更加清晰。我只是混淆了像這樣的深層嵌套函數定義。我很確定我明白。在我接受之前,讓我先玩一下。 – Falmarri 2010-12-20 17:30:26