从装饰器传递位置参数时如何支持静态和类方法?
Posted
技术标签:
【中文标题】从装饰器传递位置参数时如何支持静态和类方法?【英文标题】:How to support static and class methods when passing positional arguments from a decorator? 【发布时间】:2016-07-03 16:46:55 【问题描述】:我想编写一个装饰器,它在第一个位置(但在self
或cls
之后)将附加位置参数传递给包装函数。
def handle_route(self, url, headers):
pass
@require_login
def handle_route(self, user, url, headers):
pass
既然有静态方法、类方法和普通方法,我怎么知道在什么位置传递附加参数?
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
此示例仅用于静态方法。在其他情况下,用户作为 self
或 cls
参数传递,从而导致错误。
【问题讨论】:
【参考方案1】:最好使用装饰器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
【讨论】:
以上是关于从装饰器传递位置参数时如何支持静态和类方法?的主要内容,如果未能解决你的问题,请参考以下文章