裝飾器是乙個函式,其主要用途是包裝另乙個函式或類。這種包裝的首要目的是透明地修改或增強包裝物件的行為。表示裝飾器的語法是特殊符號@,如下所示:
@trace
def square(x):
return x*x
上面的**可以簡化為:
def square(x):
return x*x
square = trace(square)
這個例子中定義了函式square()。但在定義之後,函式物件本身就立即被傳遞給函式trace(),後者返回乙個物件替代原始的square。現在,讓我們考慮trace的實現,從而說明這樣做的用處:
enable_tracing = true
if enable_tracing:
debug_log = open('debug.log','w')
def trace(func):
if enable_tracing:
def callf(*args, **kwargs):
debug_log.write("calling %s: %s, %s\n" % (func.__name__, args, kwargs))
r = func(*args, **kwargs)
debug_log.write("%s returned %s\n" % (func.__name__, r))
return r
return callf
else:
return func
在這段**中,trace()建立了寫有一些除錯輸出的包裝器函式。然後呼叫了原始函式物件。因此如果呼叫square()函式,看到的將是包裝器中write()方法的輸出。trace()函式返回的函式callf是乙個閉包,用於替換原始的函式。關於這種實現的乙個有趣方面是,跟蹤功能本身只能像上面這樣使用全域性變數enable_tracing來啟用。如果把這個變數設定為false,trace()裝飾器只是返回未修改的原始函式。因此,禁用跟蹤時,使用裝飾器不會增加效能負擔。
使用裝飾器時,他們必須出現在函式或類定義之前的單獨行上。可以同時使用多個裝飾器,例如:
@foo
@bar
@spam
def grok(x):
pass
在這個例子中,裝飾器按照他們出現的先後順序應用,結果是:
def grok(x):
pass
grok = foo(bar(spam(grok)))
裝飾器也可以接受引數,例如:
@eventhandler('button')
def handle_button(msg):
...@eventhandler('reset')
def handle_reset(msg):
...
如果提供引數,裝飾器的語義如下所示:
def handle_button(msg):
...temp = eventhandler('button') #使用提供的引數呼叫裝飾器
handle_button = temp(handle_button) #呼叫裝飾器返回的函式
在這個例子中,裝飾器函式只接受帶有@描述符的引數。它接著返回在呼叫時使用函式作為引數的函式。下面給出了乙個例子:
#事件處理程式裝飾器
event_handlers = {}
def eventhandler(event):
def register_function(f):
event_handlers[event] = f
return f
return register_function
裝飾器也可以應用於類定義,例如:
@foo
class bar(object):
def __init__(self, x):
self.x = x
def spam(self):
statements
對於類裝飾器,應該讓裝飾器函式始終返回類物件作為結果。需要使用原始類定義的**可能要直接引用類成員,如bar.spam。如果裝飾器函式foo()返回乙個函式,這種引用就是不正確的 柯里化與python裝飾器
def add x,y return x y def add x,y prtint output return x y def add x,y return x y deftest fn print begin 增強的輸出 print end 增強的功能 return fnprint test ad...
python裝飾器 Python 裝飾器
簡言之,python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是乙個函式,使用python裝飾器的好處就是在不用更改原函式的 前提下給函式增加新的功能。一般而言,我們要想拓展原來函式 最直接的辦法就是侵入 裡面修改,例如 這是我們最原始的的乙個函式,然後我們試圖記錄...
python裝飾器 裝飾器
由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。def now print 2015 3 25 f now f 2015 3 25 函式物件有乙個 name 屬性,可以拿到函式的名字 now.name now f.name now 現在,假設我們要增強now 函式的...