使用相同的装饰(带参数)与函数和方法 [英] Using the same decorator (with arguments) with functions and methods
问题描述
我一直在试图创建一个可与蟒蛇函数和方法中使用的装饰。这在它自己并不难,但创建一个装饰接受参数时,它似乎是。
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屋!