使用装饰器作为包装器

时间:2017-07-27 18:39:42

标签: python

我有一个我在类方法上使用的装饰器。但是我想使用相同的装饰器而不是包装器。

例如,这就是我使用装饰器的方式:

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)

1 个答案:

答案 0 :(得分:2)

首先从@authenticate定义中移除MyService.execute装饰器。然后,当您需要使用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