使用相同的装饰(带参数)与函数和方法 [英] Using the same decorator (with arguments) with functions and methods

查看:130
本文介绍了使用相同的装饰(带参数)与函数和方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图创建一个可与蟒蛇函数和方法中使用的装饰。这在它自己并不难,但创建一个装饰接受参数时,它似乎是。

I have been trying to create a decorator that can be used with both functions and methods in python. This on it's own is not that hard, but when creating a decorator that takes arguments, it seems to be.

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)

以上code正确地包装了函数/方法,但在方法的情况下,在要求的说法是它是在不操作实例第一个非自我的说法。

The above code wraps the function/method correctly, but in the case of a method, the request argument is the instance it is operating on, not the first non-self argument.

有没有办法告诉如果被应用到一个函数,而不是一个方法装饰,以及相应的处理?

Is there a way to tell if the decorator is being applied to a function instead of a method, and deal accordingly?

推荐答案

要扩大对 __ __ GET 办法。这可以概括为一个装饰装饰。

To expand on the __get__ approach. This can be generalized into a 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

在这种方式你可以让你的装饰自动适应它在使用的条件。

In this way you can just make your decorator automatically adapt to the conditions it is used in.

def allowed(*allowed_methods):
    @auto_adapt_to_methods
    def wrapper(func):
        def wrapped(request):
            if request not in allowed_methods:
                raise ValueError("Invalid method %s" % request)
            return func(request)
        return wrapped
    return wrapper

注意包装函数被调用的所有函数调用,因此不要做任何昂贵的存在。

Notice that the wrapper function is called on all function calls, so don't do anything expensive there.

装饰的用法:

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

这篇关于使用相同的装饰(带参数)与函数和方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆