2017-07-27 58 views
0

我有一個裝飾器,我在類方法上使用。不過,我想使用相同的裝飾,而是作爲包裝。使用裝飾器作爲包裝

例如,這一點我如何使用裝飾:

myDecorators.py

def authenticate(method): 
    def authenticate_and_call(service_instance, *args, **kwargs): 
     print("Authentification success") 
     #access to service_instance is needed in the decorator 
     print(service_instance.config) 
     return method(service_instance, *args, **kwargs) 

    return authenticate_and_call 

myClass.py

from myDecorators import authenticate 

class MyService: 
    def __init__(self, config): 
     self.config = config 

    @authenticate #I dont want to use a decorator here 
    def execute(self): 
     print(self.config) 
     print("MyService is executed with authentication") 

我想什麼做的是什麼如:

service_callers.py

from myClass import MyService 
from myDecorators import authenticate 

#use the decorator as a wrapper 
def execute_service_with_authentification(): 
    service = MyService({"foo":"bar"}) 
    authenticate(service.execute)(service) 

execute_service_with_authentification() 

這將返回以下錯誤:

File "c:\temp\test\myDecorators.py", line 4, in authenticate_and_call 
    return method(service_instance, *args, **kwargs) 
TypeError: execute() takes exactly 1 argument (2 given) 

回答

2

首先從MyService.execute definiton刪除@authenticate裝飾。然後,當您需要使用authenticate裝飾者時,請將您的電話打包爲:authenticate(service.execute)()

確保你改變你的裝飾以及 - 你不及格的第一個參數是自:

def authenticate(method): 
    def authenticate_and_call(*args, **kwargs): 
     print("Attempting authentication on object: {}".format(method.__self__)) 
     return method(*args, **kwargs) 
    return authenticate_and_call 
+0

@BelowtheRadar - 從包裝中移除'service_instance',只是通過相同ARGS/kwargs你給包裝函數。 – zwer

+1

@BelowtheRadar - 我已經添加了上面更改的裝飾器。由於我們將它傳遞給一個實例方法,因此它不需要第一個參數。上面的內容適用於你的結構,並且也適用於你想傳遞的任何參數(注意'裸體'電話,因爲它在我原來的答案中,我最初並沒有看着裝飾者) – zwer

+1

@BelowtheRadar - 你不喜歡不需要訪問它,你傳遞的方法已經綁定到'service'實例。但是,如果你在實際調用方法之前需要對它做些什麼,你可以從它的綁定方法中'提取':'method .__ self__'。檢查上面的更新。 – zwer