2012-07-11 88 views
1

目前,我有下面的代碼,它使用一個Python庫:發送一條蟒蛇裝飾方法作爲函數參數

f = Foo(original_method, parameters) 

我想增加original_method,並有裝飾添加幾行代碼。我們來調用新的裝飾方法decorated_method。最後我想有這樣的事情:

f = Foo(decorated_method(original_method), parameters) 

我的問題是:這可能嗎?裝飾工看起來如何? 我必須說我無法擴展original_method,因爲它是外部庫的一部分。

編輯:original_method不執行,只傳遞給Foo作爲參數。 decorated_method函數應該執行一些日誌記錄並收集一些調用次數的統計信息。

稍後編輯:以下示例中的代碼正常工作。我有一些額外的問題,因爲original_method有幾個屬性,所以這是最後的代碼:

def decorated_method(method): 

    def _reporter(*args, **kwargs): 
     addmetric('apicall', method.__name__) 
     return method(*args, **kwargs) 

    _reporter.original_method_attribute = method.original_method_attribute 
    return _reporter 
+1

到目前爲止發佈的兩個答案都回答你的問題,但你的編輯說你還沒有理解他們。試試建議的內容,看看會發生什麼。裝飾器用一個包裝原始的新函數替換你的original_method。當新功能被調用時,它可以收集統計數據,然後調用原始數據。 'original_method'不被裝飾器調用,只有當'Foo'裏面的代碼調用它時。 – Duncan 2012-07-11 11:48:01

+0

我終於明白了。謝謝! – Alex 2012-07-11 12:08:37

回答

2

你不提你想decorated_method做什麼,但是這當然是可能的:

def decorated_method(f): 
    def _wrapped(*args, **kwargs): 
     print "About to call f!" 
     ret = f(*args, **kwargs) 
     print "Just got finished with f, ret = %r" % (ret,) 
     return ret 
    return _wrapped 

這只是標準的裝飾器結構:裝飾器是一種接受函數並返回函數的函數。

+0

我真的不明白這是如何工作的。不應該Foo收到與original_method相同類型的參數嗎? – Alex 2012-07-11 11:08:13

+0

@Alex:當然,它確實如此。它獲得了一個可調用函數。當一個函數聲明接受'(* args,** kwargs)'時,它可以接受任何參數,然後以相同的方式將它們傳遞給另一個函數。這就是'_wrapped'可以以相同的方式任意調用並調用'f'。 – 2012-07-11 11:11:25

+0

問題是decorated_method不應該調用原始方法,它應該用一些日誌記錄和統計信息來增加它。它應該原樣返回original_method,因爲它只是Foo的一個參數。這可能嗎? – Alex 2012-07-11 11:23:14

0

絕對:

def decorated_method(fn): 
    def inner_method(*args, **kwargs): 
     print("before calling") 
     result = fn(*args, **kwargs) 
     print("after calling") 
     return result 
    return inner_method 

一旦你得到了這個工作,你應該看看signature-preserving decorators

+0

訣竅是我實際上沒有調用original_method,我只是將它作爲參數發送給Foo。我想在decorated_method中執行的操作是收集一些統計數據。 – Alex 2012-07-11 11:15:09