2012-11-17 46 views
1

我已經寫了一個裝飾器來認證調用。它只用一個參數就可以正常工作,但更多時它不會觸發inner() takes exactly 1 argument (2 given)。自從我使用Tornado後,我有一點回撥意大利麪條,但我不確定最好的方法是什麼。python裝飾函數與多個參數(龍捲風)

#this works 
class FirstHandler(BaseHandler): 

    @asynchronous 
    @oauth_machine.auth 
    def post(self): 
     print self.user 
     self.finish() 

#this now also does 
class SecondHandler(BaseHandler): 

    @asynchronous 
    @oauth_machine.auth 
    def get(self, args): 
     self.write("ok") 
     self.finish() 

的裝飾功能(S)

def auth(fn): 
    def inner(self, *args): 
     res = get_user_by_credentials(self, fn, args, callback=done_auth) 
    return inner 

def get_user_by_credentials(self, fn, callback): 

    def onFetchUserCredentials(result, error): 
     self.user = result 
     callback(self, fn, args) 

    email = self.get_argument("email") 
    password = self.get_argument("password") 
    settings.DB.users.find_one({'email': email, 'password': password }, callback=onFetchUserCredentials) 

def done_auth(result, fn, args): 
    return fn(result, args) 

編輯:

更新代碼,工作版本。

謝謝!

+0

更改'def inner(self):'到'def inner(* args):'並且打印args'來查看傳入的參數。 – Blender

+0

我得到了在函數中傳遞的兩個參數。通過將'self'改爲'args [0]',我仍然得到一個'get()只需要2個參數(1給定)'。我在哪裏不通過第二個參數? –

+0

您沒有任何調用'get'的代碼。假設你已經發布了所有相關的代碼,這意味着它是Tornado內部的一個東西,它會不正確地調用你的「get」,這可能意味着你不適當地調用Tornado中的某些東西。發佈堆棧跟蹤,以便我們可以看到。 – abarnert

回答

1

我一開始以爲這個問題很簡單,但是你發佈了一條跟蹤原始錯誤信息的追蹤。但是,我認爲這個問題仍然非常簡單,假設回溯錯誤是正確的。回想一下,這樣的:

@decorator 
def foo(x): 
    return x + 1 

簡直是語法糖這樣的:

def foo(x): 
    return x + 1 
foo = oauth_machine.auth(foo) 

所以,當你在get使用@oauth_machine.auth,它是通過一個封閉傳遞到innerfn

def auth(fn): 
    def inner(self): 
     res = get_user_by_credentials(self, fn, callback=done_auth) 
    return inner 

它然後進入get_user_by_credentials,再次作爲fn,這反過來又產生另一種閉合,它傳遞到fncallback

def get_user_by_credentials(self, fn, callback): 

    def onFetchUserCredentials(result, error): 
     self.user = result 
     callback(self, fn) 

callback被定義爲done_auth回到inner,使menas是fn(即原來的get)傳遞那裏,然後叫上result

def done_auth(result, fn): 
    return fn(result) 

fn(即get)有兩個參數。你只傳遞一個,導致錯誤。

+1

嘿,謝謝你的解剖!在這段時間裏,我得到了它的工作(更新了代碼),你完全正確 - get()在經過裝飾器後被觸發,但done_auth()缺少一個參數。我不得不從封閉反彈到關閉。乾杯! –