从装饰器传递位置参数时如何支持静态和 class 方法?
How to support static and class methods when passing positional arguments from a decorator?
我想编写一个装饰器,它在第一个位置传递一个额外的位置参数,但在 self
或 cls
之后传递给包装函数。
def handle_route(self, url, headers):
pass
@require_login
def handle_route(self, user, url, headers):
pass
既然有staticmethods、classmethods和normal methods,我怎么知道在什么位置传递附加参数?
import functools
def require_login(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
user = obtain_user(kwargs.get('headers', {}))
return function(user, *args, **kwargs)
return wrapper
这个例子只针对staticmethods。在其他情况下,用户作为 self
或 cls
参数传递导致错误。
最好使用装饰器class,而不是装饰器函数。然后您可以实现完整的 descriptor protocol,否则它是从函数继承的。
具体来说,您需要为您的对象创建一个 __get__
方法。然后,您可以将 class-/static-/regular-method 的解析推迟到包装方法。
class RequireLogin(object):
def __init__(self, wrapee):
self.wrapee = wrapee
self.user = 'foo' # changeme
def __get__(self, instance, owner):
def wrapped(*args, **kwargs):
return self.wrapee.__get__(instance, owner)(self.user, *args, **kwargs)
# ^ use class/static/regular method's __get__
return wrapped
我想编写一个装饰器,它在第一个位置传递一个额外的位置参数,但在 self
或 cls
之后传递给包装函数。
def handle_route(self, url, headers):
pass
@require_login
def handle_route(self, user, url, headers):
pass
既然有staticmethods、classmethods和normal methods,我怎么知道在什么位置传递附加参数?
import functools
def require_login(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
user = obtain_user(kwargs.get('headers', {}))
return function(user, *args, **kwargs)
return wrapper
这个例子只针对staticmethods。在其他情况下,用户作为 self
或 cls
参数传递导致错误。
最好使用装饰器class,而不是装饰器函数。然后您可以实现完整的 descriptor protocol,否则它是从函数继承的。
具体来说,您需要为您的对象创建一个 __get__
方法。然后,您可以将 class-/static-/regular-method 的解析推迟到包装方法。
class RequireLogin(object):
def __init__(self, wrapee):
self.wrapee = wrapee
self.user = 'foo' # changeme
def __get__(self, instance, owner):
def wrapped(*args, **kwargs):
return self.wrapee.__get__(instance, owner)(self.user, *args, **kwargs)
# ^ use class/static/regular method's __get__
return wrapped