python裡的裝飾器

2021-06-01 05:28:46 字數 2202 閱讀 9599

裝飾器是乙個函式,其主要用途是包裝另乙個函式或類。這種包裝的首要目的是透明地修改或增強包裝物件的行為。表示裝飾器的語法是特殊符號@,如下所示:

@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 函式的...