对函数和方法使用相同的装饰器(带参数) [英] Using the same decorator (with arguments) with functions and methods
问题描述
我一直在尝试创建一个装饰器,它可以与 Python 中的函数和方法一起使用.这本身并不难,但是当创建一个带参数的装饰器时,它似乎是.
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)
上面的代码正确地包装了函数/方法,但在方法的情况下,request
参数是它正在操作的实例,而不是第一个非 self 参数.
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屋!