对函数和方法使用相同的修饰符(带参数)

2024-03-28 09:56:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在尝试创建一个可以在python中同时使用函数和方法的decorator。这本身并不是那么难,但是当创建一个需要参数的decorator时,似乎是这样。在

class methods(object):
    def __init__(self, *_methods):
        self.methods = _methods

    def __call__(self, func): 
        def inner(request, *args, **kwargs):
            print request
            return func(request, *args, **kwargs)
        return inner

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        new_func = self.func.__get__(obj, type)
        return self.__class__(new_func)

上面的代码正确地包装了函数/方法,但是在方法的情况下,request参数是它操作的实例,而不是第一个非自参数。在

有没有一种方法可以告诉decorator是否应用于函数而不是方法,并相应地进行处理?在


Tags: 方法函数selfobj参数returnrequestdef
3条回答

扩展__get__方法。这可以概括为decorator-decorator。在

class _MethodDecoratorAdaptor(object):
    def __init__(self, decorator, func):
        self.decorator = decorator
        self.func = func
    def __call__(self, *args, **kwargs):
        return self.decorator(self.func)(*args, **kwargs)
    def __get__(self, instance, owner):
        return self.decorator(self.func.__get__(instance, owner))

def auto_adapt_to_methods(decorator):
    """Allows you to use the same decorator on methods and functions,
    hiding the self argument from the decorator."""
    def adapt(func):
        return _MethodDecoratorAdaptor(decorator, func)
    return adapt

这样,您就可以让您的装饰器自动适应它所使用的条件。在

^{pr2}$

请注意,包装器函数是在所有函数调用中调用的,所以不要在那里做任何昂贵的操作。在

装饰工的使用:

class Foo(object):
    @allowed('GET', 'POST')
    def do(self, request):
        print "Request %s on %s" % (request, self)

@allowed('GET')
def do(request):
    print "Plain request %s" % request

Foo().do('GET')  # Works
Foo().do('POST') # Raises

因为您已经定义了一个__get__来在绑定方法上使用修饰符,所以可以传递一个标志,告诉它它是否正在方法或函数上使用。在

class methods(object):
    def __init__(self, *_methods, called_on_method=False):
        self.methods = _methods
        self.called_on_method

    def __call__(self, func):
        if self.called_on_method:
            def inner(self, request, *args, **kwargs):
                print request
                return func(request, *args, **kwargs)
        else:
            def inner(request, *args, **kwargs):
                print request
                return func(request, *args, **kwargs)
        return inner

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        new_func = self.func.__get__(obj, type)
        return self.__class__(new_func, called_on_method=True)

decorator总是应用于函数对象——让decorator print作为其参数的类型,这样您就可以确认了;而且它通常也应该返回一个函数对象(它已经是一个具有正确的__get__的装饰器了!-)尽管后者也有例外。在

也就是说,在准则中:

class X(object):

  @deco
  def f(self): pass

在类主体中调用deco(f),并且,当您还在那里时,f是一个函数,而不是方法类型的实例。(当稍后的f作为X的属性或其实例被访问时,该方法在f的{}中生成并返回)。在

也许你能更好地解释一下你想让你的装饰师使用的玩具,这样我们可以提供更多的帮助。。。?在

编辑:这也适用于带参数的装饰器,即

^{pr2}$

那么在类主体中调用的deco(23)(f)f仍然是一个函数对象,当作为参数传递给可调用的{}返回的任何内容时,该可调用对象仍应返回一个函数对象(一般情况下,有例外;-)。在

相关问题 更多 >