2008-12-04 138 views
5

舉個例子,Python裝飾器在它裝飾的函數被調用之前運行?

def get_booking(f=None): 
    print "Calling get_booking Decorator" 
    def wrapper(request, **kwargs): 
     booking = _get_booking_from_session(request) 
     if booking == None: 
      # we don't have a booking in our session. 
      return HttpRedirect('/') 
     else: 
      return f(request=request, booking=booking, **kwargs) 
    return wrapper 

@get_booking 
def do_stuff(request, booking): 
    # do stuff here 

我遇到的問題是,在@get_booking裝飾正在我之前也叫,我裝飾功能調用。

輸出的開始:

Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
[26/Oct/2008 19:54:04] "GET /onlinebooking/?id=1,2 HTTP/1.1" 302 0 
[26/Oct/2008 19:54:05] "GET /onlinebooking/ HTTP/1.1" 200 2300 
[26/Oct/2008 19:54:05] "GET /site-media/css/style.css HTTP/1.1" 200 800 
[26/Oct/2008 19:54:05] "GET /site-media/css/jquery-ui-themeroller.css HTTP/1.1" 200 25492 

我還沒有還送被裝飾在這一點上的函數的調用。

我剛剛開始與裝飾,所以也許我失去了一些東西。任何幫助?

+0

要直接回答問題標題,請在裝飾函數**之前運行裝飾器。不,它在聲明函數時不運行。它在函數爲_called_時運行。我希望這有幫助。 – Jess 2016-10-27 14:50:35

回答

25

我相信python裝飾器只是語法糖。

@foo 
def bar(): 
    pass 

是一回事

def bar(): 
    pass 
bar = foo(bar) 

正如你所看到的,被稱爲即使酒吧尚未調用。這就是你看到裝飾器函數的輸出的原因。你的輸出應該包含你爲裝飾器應用的每個函數的一行。

0

一旦裝飾函數被定義,就會調用裝飾器。它等同於寫這樣的事情:

def __do_stuff(...): 
    ... 

do_stuff = get_booking(__do_stuff) 
0

蟒蛇裝飾應用到函數的函數來轉換它:

@my_decorator 
def function(): ... 

就像這樣:

def function():... 
function = my_decorator(function) 

你想要什麼要做的是:

def get_booking(f=None): 
    def wrapper(request, **kwargs): 
     print "Calling get_booking Decorator" 
     booking = _get_booking_from_session(request) 
     if booking == None: 
      # we don't have a booking in our session. 
      return HttpRedirect('/') 
     else: 
      return f(request=request, booking=booking, **kwargs) 
    return wrapper 
+0

給裝飾器中的目標函數賦予默認值有什麼好處? – muhuk 2008-12-04 22:31:40

2

由於您已經開始使用裝飾器,因此我認爲閱讀這些內容會有所幫助,以便您事先知道陷阱和解決方法。

這裏有兩個鏈接,以前討論裝飾。

Python decorator makes function forget that it belongs to a class What does functools.wraps do?

而且,第二連桿提到「functools」的高階函數的模塊,其作用於或返回其它功能。建議使用functools.wraps,因爲它保留了原始函數的文檔字符串(裝飾一)。

另一個問題是錯誤的方法簽名,同時爲我的項目生成自動文檔。 但有一個解決方法: Preserving signatures of decorated functions

希望這會有所幫助。